|
|
|
/*==LICENSE==*
|
|
|
|
|
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools
|
|
|
|
Copyright (C) 2011 Cyan Worlds, Inc.
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
Additional permissions under GNU GPL version 3 section 7
|
|
|
|
|
|
|
|
If you modify this Program, or any covered work, by linking or
|
|
|
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
|
|
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
|
|
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
|
|
|
(or a modified version of those libraries),
|
|
|
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
|
|
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
|
|
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
|
|
|
licensors of this Program grant you additional
|
|
|
|
permission to convey the resulting work. Corresponding Source for a
|
|
|
|
non-source form of such a combination shall include the source code for
|
|
|
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
|
|
|
work.
|
|
|
|
|
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|
|
|
or by snail mail at:
|
|
|
|
Cyan Worlds, Inc.
|
|
|
|
14617 N Newport Hwy
|
|
|
|
Mead, WA 99021
|
|
|
|
|
|
|
|
*==LICENSE==*/
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// //
|
|
|
|
// plMipmap Class Header //
|
|
|
|
// Derived bitmap class representing a single mipmap. //
|
|
|
|
// Cyan, Inc. //
|
|
|
|
// //
|
|
|
|
//// Version History //////////////////////////////////////////////////////////
|
|
|
|
// //
|
|
|
|
// 6.7.2001 mcn - Created. //
|
|
|
|
// //
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#ifndef _plMipmap_h
|
|
|
|
#define _plMipmap_h
|
|
|
|
|
|
|
|
#include "plBitmap.h"
|
|
|
|
|
|
|
|
#ifdef HS_DEBUGGING
|
|
|
|
#define ASSERT_PIXELSIZE(bitmap, pixelsize) hsAssert((bitmap)->fPixelSize == (pixelsize), "pixelSize mismatch")
|
|
|
|
#define ASSERT_XY(bitmap, x, y) hsAssert(x < (bitmap)->fWidth && y < (bitmap)->fHeight, "bad XY")
|
|
|
|
#define ASSERT_UNCOMPRESSED() hsAssert(fCompressionType!=kDirectXCompression, "Can't operate on compressed map.")
|
|
|
|
|
|
|
|
// Define the following konstant to enable mipmap leak checking. This is because our normal
|
|
|
|
// memory manager sucks when trying to track down these problems
|
|
|
|
#define MEMORY_LEAK_TRACER
|
|
|
|
#else
|
|
|
|
#define ASSERT_PIXELSIZE(bitmap, pixelsize)
|
|
|
|
#define ASSERT_XY(bitmap, x, y)
|
|
|
|
#define ASSERT_UNCOMPRESSED()
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//// Class Definition /////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
class plBitmapCreator;
|
|
|
|
class plTextGenerator;
|
|
|
|
|
|
|
|
class plMipmap : public plBitmap
|
|
|
|
{
|
|
|
|
friend class plBitmapCreator;
|
|
|
|
friend class plTextGenerator;
|
|
|
|
|
|
|
|
public:
|
|
|
|
//// Public Flags ////
|
|
|
|
|
|
|
|
|
|
|
|
//// Public Data /////
|
|
|
|
|
|
|
|
|
|
|
|
//// Public Members ////
|
|
|
|
|
|
|
|
|
|
|
|
plMipmap();
|
|
|
|
plMipmap( UInt32 width, UInt32 height, unsigned config, UInt8 numLevels = 0, UInt8 compType = kUncompressed, UInt8 format = UncompressedInfo::kRGB8888 );
|
|
|
|
plMipmap( plMipmap *bm, hsScalar sig, UInt32 createFlags,
|
|
|
|
hsScalar detailDropoffStart, hsScalar detailDropoffStop,
|
|
|
|
hsScalar detailMax, hsScalar detailMin );
|
|
|
|
virtual ~plMipmap();
|
|
|
|
|
|
|
|
CLASSNAME_REGISTER( plMipmap );
|
|
|
|
GETINTERFACE_ANY( plMipmap, plBitmap );
|
|
|
|
|
|
|
|
|
|
|
|
void Create( UInt32 width, UInt32 height, unsigned config, UInt8 numLevels, UInt8 compType = kUncompressed, UInt8 format = UncompressedInfo::kRGB8888 );
|
|
|
|
|
|
|
|
virtual void Reset();
|
|
|
|
|
|
|
|
// Get the total size in bytes
|
|
|
|
virtual UInt32 GetTotalSize() const;
|
|
|
|
|
|
|
|
virtual void Read( hsStream *s, hsResMgr *mgr ) { hsKeyedObject::Read( s, mgr ); this->Read( s ); }
|
|
|
|
virtual void Write( hsStream *s, hsResMgr *mgr ) { hsKeyedObject::Write( s, mgr ); this->Write( s ); }
|
|
|
|
|
|
|
|
virtual UInt8 GetNumLevels() const { return fNumLevels; }
|
|
|
|
virtual UInt32 GetLevelSize( UInt8 level ); // 0 is the largest
|
|
|
|
|
|
|
|
virtual void Colorize();
|
|
|
|
virtual plMipmap *Clone() const;
|
|
|
|
virtual void CopyFrom( const plMipmap *source );
|
|
|
|
|
|
|
|
inline UInt32 GetWidth() const { return fWidth; }
|
|
|
|
inline UInt32 GetHeight() const { return fHeight; }
|
|
|
|
inline UInt32 GetRowBytes() const { return fRowBytes; }
|
|
|
|
|
|
|
|
void *GetImage() const { return fImage; }
|
|
|
|
void SetImagePtr( void *ptr ) { fImage = ptr; }
|
|
|
|
UInt8 *GetLevelPtr( UInt8 level, UInt32 *width = nil, UInt32 *height = nil, UInt32 *rowBytes = nil );
|
|
|
|
|
|
|
|
// Sets the current level pointer for use with GetAddr*
|
|
|
|
virtual void SetCurrLevel(UInt8 level);
|
|
|
|
void *GetCurrLevelPtr() const { return fCurrLevelPtr; }
|
|
|
|
UInt32 GetCurrWidth() const { return fCurrLevelWidth; }
|
|
|
|
UInt32 GetCurrHeight() const { return fCurrLevelHeight; }
|
|
|
|
UInt32 GetCurrLevelSize() const { return fLevelSizes[ fCurrLevel ]; }
|
|
|
|
UInt32 GetCurrLevel() const { return fCurrLevel; }
|
|
|
|
|
|
|
|
// These methods return the address of the pixel specified by x and y
|
|
|
|
// They are meant to be fast, therefore they are inlined and do not check
|
|
|
|
// the fPixelSize field at runtime (except when debugging)
|
|
|
|
|
|
|
|
UInt8* GetAddr8(unsigned x, unsigned y) const
|
|
|
|
{
|
|
|
|
ASSERT_PIXELSIZE(this, 8);
|
|
|
|
ASSERT_XY(this, x, y);
|
|
|
|
ASSERT_UNCOMPRESSED();
|
|
|
|
return (UInt8*)((char*)fCurrLevelPtr + y * fCurrLevelRowBytes + x);
|
|
|
|
}
|
|
|
|
UInt16* GetAddr16(unsigned x, unsigned y) const
|
|
|
|
{
|
|
|
|
ASSERT_PIXELSIZE(this, 16);
|
|
|
|
ASSERT_XY(this, x, y);
|
|
|
|
ASSERT_UNCOMPRESSED();
|
|
|
|
return (UInt16*)((char*)fCurrLevelPtr + y * fCurrLevelRowBytes + (x << 1));
|
|
|
|
}
|
|
|
|
UInt32* GetAddr32(unsigned x, unsigned y) const
|
|
|
|
{
|
|
|
|
ASSERT_PIXELSIZE(this, 32);
|
|
|
|
ASSERT_XY(this, x, y);
|
|
|
|
ASSERT_UNCOMPRESSED();
|
|
|
|
return (UInt32*)((char*)fCurrLevelPtr + y * fCurrLevelRowBytes + (x << 2));
|
|
|
|
}
|
|
|
|
void* GetAddr64(unsigned x, unsigned y) const
|
|
|
|
{
|
|
|
|
ASSERT_PIXELSIZE(this, 64);
|
|
|
|
ASSERT_XY(this, x, y);
|
|
|
|
ASSERT_UNCOMPRESSED();
|
|
|
|
return (void*)((char*)fCurrLevelPtr + y * fCurrLevelRowBytes + (x << 3));
|
|
|
|
}
|
|
|
|
|
|
|
|
// This sets fPixelSize, fSpace, fFlags, for you
|
|
|
|
// All you need to set is
|
|
|
|
// fWidth, fHeight, fRowBytes, fImage and fColorTable
|
|
|
|
enum {
|
|
|
|
kColor8Config = 0,
|
|
|
|
kGray44Config = 1,
|
|
|
|
kGray4Config = 2,
|
|
|
|
kGray8Config = 8, // So we can use bit depths instead
|
|
|
|
kRGB16Config = 16,
|
|
|
|
kRGB32Config = 24,
|
|
|
|
kARGB32Config = 32,
|
|
|
|
};
|
|
|
|
|
|
|
|
void SetConfig( unsigned config );
|
|
|
|
|
|
|
|
|
|
|
|
//// Really complex creation stuff ////
|
|
|
|
|
|
|
|
enum {
|
|
|
|
kCreateDetailAlpha = 0x1,
|
|
|
|
kCreateDetailAdd = 0x2,
|
|
|
|
kCreateDetailMult = 0x4,
|
|
|
|
kCreateDetailMask = kCreateDetailAlpha | kCreateDetailAdd | kCreateDetailMult,
|
|
|
|
kCreateCarryAlpha = 0x8,
|
|
|
|
kCreateCarryWhite = 0x10,
|
|
|
|
kCreateCarryBlack = 0x20,
|
|
|
|
kCreateCarryMask = kCreateCarryAlpha | kCreateCarryWhite | kCreateCarryBlack
|
|
|
|
};
|
|
|
|
enum hsGPixelType {
|
|
|
|
kPixelARGB4444,
|
|
|
|
kPixelARGB1555,
|
|
|
|
kPixelAI88,
|
|
|
|
kPixelI8
|
|
|
|
};
|
|
|
|
enum hsGCopyOptions {
|
|
|
|
kCopyLODMask,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
kColorDataRLE = 0x1,
|
|
|
|
kAlphaDataRLE = 0x2
|
|
|
|
};
|
|
|
|
|
|
|
|
void SetBitmapAsLevel(UInt8 iDst, plMipmap *bm, hsScalar sig, UInt32 createFlags,
|
|
|
|
hsScalar detailDropoffStart, hsScalar detailDropoffStop,
|
|
|
|
hsScalar detailMax, hsScalar detailMin);
|
|
|
|
void ICreateLevelNoDetail(UInt8 iDst, const plFilterMask& mask);
|
|
|
|
void IBlendLevelDetailAlpha(UInt8 iDst, const plFilterMask& mask,
|
|
|
|
hsScalar detailDropoffStart, hsScalar detailDropoffStop,
|
|
|
|
hsScalar detailMax, hsScalar detailMin);
|
|
|
|
void IBlendLevelDetailAdd(UInt8 iDst, const plFilterMask& mask,
|
|
|
|
hsScalar detailDropoffStart, hsScalar detailDropoffStop,
|
|
|
|
hsScalar detailMax, hsScalar detailMin);
|
|
|
|
void IBlendLevelDetailMult(UInt8 iDst, const plFilterMask& mask,
|
|
|
|
hsScalar detailDropoffStart, hsScalar detailDropoffStop,
|
|
|
|
hsScalar detailMax, hsScalar detailMin);
|
|
|
|
void Filter(hsScalar sig);
|
|
|
|
UInt32 CopyOutPixels(UInt32 destXSize, UInt32 destYSize, UInt32 dstFormat, void *destPixels, UInt32 copyOptions);
|
|
|
|
|
|
|
|
void ClipToMaxSize( UInt32 maxDimension );
|
|
|
|
void RemoveMipping();
|
|
|
|
|
|
|
|
void EnsureKonstantBorder( hsBool clampU, hsBool clampV );
|
|
|
|
|
|
|
|
enum CompositeFlags
|
|
|
|
{
|
|
|
|
kForceOpaque = 0x0001, // Copy src pixels raw, force dest alphas to opaque
|
|
|
|
kCopySrcAlpha = 0x0002, // Copy the src pixels raw, including alphas, overwrite dest
|
|
|
|
kBlendSrcAlpha = 0x0004, // Blend src pixels onto dest using src alpha, dest alpha = src alpha
|
|
|
|
kMaskSrcAlpha = 0x0008, // Same as copySrcAlpha, but dest is untouched when src alpha = 0
|
|
|
|
kBlendWriteAlpha= 0x0010 // Like default (0), but writes dest alpha values
|
|
|
|
};
|
|
|
|
|
|
|
|
class CompositeOptions
|
|
|
|
{
|
|
|
|
// Helper class for specifying options to Composite()
|
|
|
|
public:
|
|
|
|
UInt16 fFlags;
|
|
|
|
UInt8 fSrcLevelsToSkip;
|
|
|
|
UInt8 fOpacity;
|
|
|
|
hsScalar fRedTint, fGreenTint, fBlueTint;
|
|
|
|
UInt16 fSrcClipX, fSrcClipY; // Clipping is applied AFTER levelSkip
|
|
|
|
UInt16 fSrcClipWidth, fSrcClipHeight; // 0 means max width/height
|
|
|
|
|
|
|
|
CompositeOptions() { fFlags = 0; fSrcLevelsToSkip = 0; fRedTint = fGreenTint = fBlueTint = 1.f;
|
|
|
|
fSrcClipX = fSrcClipY = fSrcClipWidth = fSrcClipHeight = 0; fOpacity = 255;}
|
|
|
|
|
|
|
|
CompositeOptions( UInt16 flags, UInt8 srcLevelsToSkip = 0, hsScalar red = 1.f, hsScalar green = 1.f,
|
|
|
|
hsScalar blue = 1.f, UInt16 srcClipX = 0, UInt16 srcClipY = 0,
|
|
|
|
UInt16 srcClipWidth = 0, UInt16 srcClipHeight = 0, UInt8 opacity = 255 )
|
|
|
|
{
|
|
|
|
fFlags = flags;
|
|
|
|
fSrcLevelsToSkip = srcLevelsToSkip;
|
|
|
|
fRedTint = red;
|
|
|
|
fGreenTint = green;
|
|
|
|
fBlueTint = blue;
|
|
|
|
fSrcClipX = srcClipX;
|
|
|
|
fSrcClipY = srcClipY;
|
|
|
|
fSrcClipWidth = srcClipWidth;
|
|
|
|
fSrcClipHeight = srcClipHeight;
|
|
|
|
fOpacity = opacity;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Compositing function. Take a (smaller) mipmap and composite it onto this one at the given location. Nil options means use default
|
|
|
|
virtual void Composite( plMipmap *source, UInt16 x, UInt16 y, CompositeOptions *options = nil );
|
|
|
|
|
|
|
|
// Scaling function
|
|
|
|
enum ScaleFilter
|
|
|
|
{
|
|
|
|
kBoxFilter,
|
|
|
|
kDefaultFilter = kBoxFilter
|
|
|
|
};
|
|
|
|
|
|
|
|
virtual void ScaleNicely( UInt32 *destPtr, UInt16 destWidth, UInt16 destHeight,
|
|
|
|
UInt16 destStride, plMipmap::ScaleFilter filter ) const;
|
|
|
|
|
|
|
|
virtual hsBool ResizeNicely( UInt16 newWidth, UInt16 newHeight, plMipmap::ScaleFilter filter );
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
//// Protected Members ////
|
|
|
|
|
|
|
|
void *fImage;
|
|
|
|
UInt32 fWidth, fHeight, fRowBytes, fTotalSize;
|
|
|
|
UInt8 fNumLevels;
|
|
|
|
UInt32 *fLevelSizes;
|
|
|
|
|
|
|
|
void *fCurrLevelPtr;
|
|
|
|
UInt8 fCurrLevel;
|
|
|
|
UInt32 fCurrLevelWidth, fCurrLevelHeight, fCurrLevelRowBytes;
|
|
|
|
|
|
|
|
void IReadRawImage( hsStream *stream );
|
|
|
|
void IWriteRawImage( hsStream *stream );
|
|
|
|
plMipmap *ISplitAlpha();
|
|
|
|
void IRecombineAlpha( plMipmap *alphaChannel );
|
|
|
|
plMipmap *IReadRLEImage( hsStream *stream );
|
|
|
|
void IWriteRLEImage( hsStream *stream, plMipmap *mipmap );
|
|
|
|
void IReadJPEGImage( hsStream *stream );
|
|
|
|
void IWriteJPEGImage( hsStream *stream );
|
|
|
|
void IBuildLevelSizes();
|
|
|
|
|
|
|
|
void IColorLevel( UInt8 level, const UInt8 *colorMask );
|
|
|
|
|
|
|
|
hsScalar IGetDetailLevelAlpha( UInt8 level, hsScalar dropStart, hsScalar dropStop, hsScalar min, hsScalar max );
|
|
|
|
|
|
|
|
void ICarryZeroAlpha(UInt8 iDst);
|
|
|
|
void ICarryColor(UInt8 iDst, UInt32 col);
|
|
|
|
|
|
|
|
hsBool IGrabBorderColor( hsBool grabVNotU, UInt32 *color );
|
|
|
|
void ISetCurrLevelUBorder( UInt32 color );
|
|
|
|
void ISetCurrLevelVBorder( UInt32 color );
|
|
|
|
|
|
|
|
virtual UInt32 Read( hsStream *s );
|
|
|
|
virtual UInt32 Write( hsStream *s );
|
|
|
|
|
|
|
|
friend class plCubicEnvironmap;
|
|
|
|
|
|
|
|
#ifdef MEMORY_LEAK_TRACER
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
class plRecord
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
plRecord *fNext;
|
|
|
|
plRecord **fBackPtr;
|
|
|
|
|
|
|
|
char fKeyName[ 256 ];
|
|
|
|
void *fImage;
|
|
|
|
UInt32 fWidth, fHeight, fRowBytes;
|
|
|
|
UInt8 fNumLevels;
|
|
|
|
UInt8 fCompressionType;
|
|
|
|
union
|
|
|
|
{
|
|
|
|
DirectXInfo fDirectXInfo;
|
|
|
|
UncompressedInfo fUncompressedInfo;
|
|
|
|
};
|
|
|
|
enum Method
|
|
|
|
{
|
|
|
|
kViaCreate,
|
|
|
|
kViaRead,
|
|
|
|
kViaClipToMaxSize,
|
|
|
|
kViaDetailMapConstructor,
|
|
|
|
kViaCopyFrom,
|
|
|
|
kViaResize
|
|
|
|
} fCreationMethod;
|
|
|
|
|
|
|
|
void Link( plRecord **backPtr )
|
|
|
|
{
|
|
|
|
fBackPtr = backPtr;
|
|
|
|
fNext = *backPtr;
|
|
|
|
if( fNext != nil )
|
|
|
|
fNext->fBackPtr = &fNext;
|
|
|
|
*backPtr = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Unlink()
|
|
|
|
{
|
|
|
|
*fBackPtr = fNext;
|
|
|
|
if( fNext != nil )
|
|
|
|
fNext->fBackPtr = fBackPtr;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static plRecord *fRecords;
|
|
|
|
static UInt32 fNumMipmaps;
|
|
|
|
|
|
|
|
static void IAddToMemRecord( plMipmap *mip, plRecord::Method method );
|
|
|
|
static void IRemoveFromMemRecord( UInt8 *image );
|
|
|
|
static void IReportLeaks();
|
|
|
|
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif // _plMipmap_h
|