diff -Naur Irrlicht/CImageLoaderWAL.cpp Irrlicht.new/CImageLoaderWAL.cpp --- Irrlicht/CImageLoaderWAL.cpp 1970-01-01 01:00:00.000000000 +0100 +++ Irrlicht.new/CImageLoaderWAL.cpp 2005-12-06 14:46:44.611472007 +0100 @@ -0,0 +1,258 @@ +/* + 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 +#include +#include "CImageLoaderWAL.h" +#include "CColorConverter.h" +#include "CImage.h" +#include "os.h" +#include "dimension2d.h" +#include "IVideoDriver.h" +#include "ISceneNodeAnimator.h" +#include "IFileSystem.h" +#include "irrString.h" +#include "CSceneNodeAnimatorTexture.h" + +namespace irr +{ +namespace video +{ + +// May or may not be fully implemented +#define TRY_LOADING_PALETTE_FROM_FILE 0 + +// Define one of these to get a default paltte for WALs. +// If you don't, WALs will be all black if the palette couldn't be loaded from a file. +#define DEFAULT_PALETTE_Q1 0 // I may add Q1 support +#define DEFAULT_PALETTE_Q2 1 + +s32 CImageLoaderWAL::DefaultPalette[256] = { +#if DEFAULT_PALETTE_Q1 +0x000000L,0x0F0F0FL,0x1F1F1FL,0x2F2F2FL,0x3F3F3FL,0x4B4B4BL,0x5B5B5BL,0x6B6B6BL,0x7B7B7BL,0x8B8B8BL,0x9B9B9BL, +0xABABABL,0xBBBBBBL,0xCBCBCBL,0xDBDBDBL,0xEBEBEBL,0x0F0B07L,0x170F0BL,0x1F170BL,0x271B0FL,0x2F2313L,0x372B17L, +0x3F2F17L,0x4B371BL,0x533B1BL,0x5B431FL,0x634B1FL,0x6B531FL,0x73571FL,0x7B5F23L,0x836723L,0x8F6F23L,0x0B0B0FL, +0x13131BL,0x1B1B27L,0x272733L,0x2F2F3FL,0x37374BL,0x3F3F57L,0x474767L,0x4F4F73L,0x5B5B7FL,0x63638BL,0x6B6B97L, +0x7373A3L,0x7B7BAFL,0x8383BBL,0x8B8BCBL,0x000000L,0x070700L,0x0B0B00L,0x131300L,0x1B1B00L,0x232300L,0x2B2B07L, +0x2F2F07L,0x373707L,0x3F3F07L,0x474707L,0x4B4B0BL,0x53530BL,0x5B5B0BL,0x63630BL,0x6B6B0FL,0x070000L,0x0F0000L, +0x170000L,0x1F0000L,0x270000L,0x2F0000L,0x370000L,0x3F0000L,0x470000L,0x4F0000L,0x570000L,0x5F0000L,0x670000L, +0x6F0000L,0x770000L,0x7F0000L,0x131300L,0x1B1B00L,0x232300L,0x2F2B00L,0x372F00L,0x433700L,0x4B3B07L,0x574307L, +0x5F4707L,0x6B4B0BL,0x77530FL,0x835713L,0x8B5B13L,0x975F1BL,0xA3631FL,0xAF6723L,0x231307L,0x2F170BL,0x3B1F0FL, +0x4B2313L,0x572B17L,0x632F1FL,0x733723L,0x7F3B2BL,0x8F4333L,0x9F4F33L,0xAF632FL,0xBF772FL,0xCF8F2BL,0xDFAB27L, +0xEFCB1FL,0xFFF31BL,0x0B0700L,0x1B1300L,0x2B230FL,0x372B13L,0x47331BL,0x533723L,0x633F2BL,0x6F4733L,0x7F533FL, +0x8B5F47L,0x9B6B53L,0xA77B5FL,0xB7876BL,0xC3937BL,0xD3A38BL,0xE3B397L,0xAB8BA3L,0x9F7F97L,0x937387L,0x8B677BL, +0x7F5B6FL,0x775363L,0x6B4B57L,0x5F3F4BL,0x573743L,0x4B2F37L,0x43272FL,0x371F23L,0x2B171BL,0x231313L,0x170B0BL, +0x0F0707L,0xBB739FL,0xAF6B8FL,0xA35F83L,0x975777L,0x8B4F6BL,0x7F4B5FL,0x734353L,0x6B3B4BL,0x5F333FL,0x532B37L, +0x47232BL,0x3B1F23L,0x2F171BL,0x231313L,0x170B0BL,0x0F0707L,0xDBC3BBL,0xCBB3A7L,0xBFA39BL,0xAF978BL,0xA3877BL, +0x977B6FL,0x876F5FL,0x7B6353L,0x6B5747L,0x5F4B3BL,0x533F33L,0x433327L,0x372B1FL,0x271F17L,0x1B130FL,0x0F0B07L, +0x6F837BL,0x677B6FL,0x5F7367L,0x576B5FL,0x4F6357L,0x475B4FL,0x3F5347L,0x374B3FL,0x2F4337L,0x2B3B2FL,0x233327L, +0x1F2B1FL,0x172317L,0x0F1B13L,0x0B130BL,0x070B07L,0xFFF31BL,0xEFDF17L,0xDBCB13L,0xCBB70FL,0xBBA70FL,0xAB970BL, +0x9B8307L,0x8B7307L,0x7B6307L,0x6B5300L,0x5B4700L,0x4B3700L,0x3B2B00L,0x2B1F00L,0x1B0F00L,0x0B0700L,0x0000FFL, +0x0B0BEFL,0x1313DFL,0x1B1BCFL,0x2323BFL,0x2B2BAFL,0x2F2F9FL,0x2F2F8FL,0x2F2F7FL,0x2F2F6FL,0x2F2F5FL,0x2B2B4FL, +0x23233FL,0x1B1B2FL,0x13131FL,0x0B0B0FL,0x2B0000L,0x3B0000L,0x4B0700L,0x5F0700L,0x6F0F00L,0x7F1707L,0x931F07L, +0xA3270BL,0xB7330FL,0xC34B1BL,0xCF632BL,0xDB7F3BL,0xE3974FL,0xE7AB5FL,0xEFBF77L,0xF7D38BL,0xA77B3BL,0xB79B37L, +0xC7C337L,0xE7E357L,0x7FBFFFL,0xABE7FFL,0xD7FFFFL,0x670000L,0x8B0000L,0xB30000L,0xD70000L,0xFF0000L,0xFFF393L, +0xFFF7C7L,0xFFFFFFL,0x9F5B53L +#elif DEFAULT_PALETTE_Q2 +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 +#endif +}; + + +CImageLoaderWAL::CImageLoaderWAL() +{ +} + + +CImageLoaderWAL::~CImageLoaderWAL() +{ +} + + +bool CImageLoaderWAL::isALoadableFileExtension(const c8* fileName) +{ + return strstr(fileName, ".wal") != 0; +} + + +bool CImageLoaderWAL::isALoadableFileFormat(irr::io::IReadFile* file) +{ + if (!file) + return false; + + return true; +} + + +IImage* CImageLoaderWAL::loadImage(irr::io::IReadFile* file) +{ + // Try to get the color palette from elsewhere (usually in a pak along with the WAL). + // If this fails we use the DefaultPalette. + 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 (s32 i = 0; i < 256; i++) { + palette[i] = paletteImage->getPixel(i, 0).color; + } + } else { + //FIXME: try reading a simple palette from "wal.pal" + palette = DefaultPalette; + } + if (paletteImage) paletteImage->drop(); + } else { + palette = DefaultPalette; + } +#else + palette = DefaultPalette; +#endif + + SWALHeader header; + + file->seek(0); + file->read(&header, sizeof(SWALHeader)); + + file->seek(header.imageOffset[0]); + + // read image + + s32 imageSize = header.ImageHeight * header.ImageWidth; + c8* data = new c8[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, 0, DefaultPalette); + + + image->unlock(); + + delete [] data; + + return image; +} + + +IImageLoader* createImageLoaderWAL() +{ + return new irr::video::CImageLoaderWAL(); +} + + + +scene::ISceneNodeAnimator * createWALTextureAnimator(io::IFileSystem * filesystem, video::IVideoDriver * driver, c8 * fileName) +{ + // You give it an animated WAL, and it'll return a CSceneNodeAnimatorTexture for it. + // If the WAL isn't animated, returns NULL.{ + + // This isn't particularly elegant since I'm working within the way Irrlicht does things (and + // am just learning Irrlicht, for that matter). + + // I'm not sure I've ever tested it. + + s32 loopPoint = -1; // Don't loop by default + + SWALHeader header; + irr::core::array list; + + core::stringc currentFile; + currentFile = core::stringc(fileName); + currentFile.make_lower(); + + while (true) { + list.push_back(currentFile); + io::IReadFile * f = filesystem->createAndOpenFile(currentFile.c_str()); + if (!f) { + // Uh oh. Missing file. + os::Printer::log("Missing WAL animation frame ", currentFile.c_str(), ELL_WARNING); + break; + } + f->read(&header, sizeof(header)); + currentFile = core::stringc(header.nextFrameName); + currentFile.make_lower(); + + if (currentFile.size() == 0) { + // No more animation info, so this is the end. + break; + } + + s32 pos; + pos = list.binary_search(currentFile); + if (pos != -1) { + // It was found, which means the animation loops at this point. + loopPoint = pos; + break; + } + } + + core::arraytextures; + textures.set_used(list.size()); + for (u32 i = 0; i < list.size(); i++) { + ITexture * tex = driver->getTexture(list[i].c_str()); + if (!tex) { + // Uh oh. Didn't load! Print a warning and try to continue loading what we can. + os::Printer::log("Missing WAL animation frame ", list[i].c_str(), ELL_WARNING); + + // If looping is on, just set loop point to 0 since a missing frame could mess up a non-zero loop point. + if (loopPoint != -1) loopPoint = 0; + + continue; + } + textures[i] = tex; + } + + if (textures.size() == 0) { + // Ack! Nothing loaded! + return NULL; + } + + // This is for my extended ISceneNodeAnimator + //irr::scene::ISceneNodeAnimator* anim = new irr::scene::CSceneNodeAnimatorTexture(textures, 500, loopPoint != -1, os::Timer::getTime(), loopPoint); + + irr::scene::ISceneNodeAnimator* anim = new irr::scene::CSceneNodeAnimatorTexture(textures, 500, loopPoint != -1, os::Timer::getTime()); + + return anim; +} + + +} +} diff -Naur Irrlicht/CImageLoaderWAL.h Irrlicht.new/CImageLoaderWAL.h --- Irrlicht/CImageLoaderWAL.h 1970-01-01 01:00:00.000000000 +0100 +++ Irrlicht.new/CImageLoaderWAL.h 2005-12-06 14:46:44.612471865 +0100 @@ -0,0 +1,70 @@ +/* + Thanks to: + Max McGuire for his Flipcode article about WAL textures + Ty Matthews for Wally, the WAL editor + Nikolaus Gebhardt for the Irrlicht 3D engine +*/ + +#ifndef __C_IMAGE_LOADER_WAL_H_INCLUDED__ +#define __C_IMAGE_LOADER_WAL_H_INCLUDED__ + +#include +#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 { + c8 frameName[32]; + + u32 ImageWidth; + u32 ImageHeight; + + s32 imageOffset[4]; + + c8 nextFrameName[32]; + + s32 flags; // surface properties, i.e. slick, sky, nodraw + s32 contents; // i.e. solid, clip, area portal + s32 value; // light + } PACK_STRUCT; + +#ifdef _MSC_VER +# pragma pack( pop, packing ) +#endif +#undef PACK_STRUCT + +class CImageLoaderWAL : public irr::video::IImageLoader +{ +public: + + CImageLoaderWAL(); + + virtual ~CImageLoaderWAL(); + + virtual bool isALoadableFileExtension(const c8* fileName); + + virtual bool isALoadableFileFormat(irr::io::IReadFile* file); + + virtual irr::video::IImage* loadImage(irr::io::IReadFile* file); + +private: + static s32 DefaultPalette[256]; +}; + +} +} + +#endif diff -Naur Irrlicht/CNullDriver.cpp Irrlicht.new/CNullDriver.cpp --- Irrlicht/CNullDriver.cpp 2005-11-27 12:01:00.000000000 +0100 +++ Irrlicht.new/CNullDriver.cpp 2005-12-06 14:34:18.924773795 +0100 @@ -27,6 +27,8 @@ 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(); @@ -57,6 +59,7 @@ SurfaceLoader.push_back(video::createImageLoaderPSD()); SurfaceLoader.push_back(video::createImageLoaderPCX()); SurfaceLoader.push_back(video::createImageLoaderPNG()); + SurfaceLoader.push_back(video::createImageLoaderWAL()); // set ExposedData to 0 memset(&ExposedData, 0, sizeof(ExposedData));