finish CKTexture reading
This commit is contained in:
@ -137,7 +137,7 @@ namespace LibCmo::CK2 {
|
||||
#pragma region Core Read / Write
|
||||
|
||||
bool CKBitmapData::ReadFromChunk(CKStateChunk* chunk, CKFileVisitor* file, const CKBitmapDataReadIdentifiers& identifiers) {
|
||||
XContainer::XBitArray notReadSlot;
|
||||
XContainer::XBitArray hasReadSlot;
|
||||
|
||||
// check 3 types enbedded image
|
||||
// MARK: i think there is a potential vulnerable issue.
|
||||
@ -152,7 +152,7 @@ namespace LibCmo::CK2 {
|
||||
chunk->ReadStruct(bpp);
|
||||
|
||||
SetSlotCount(slotcount);
|
||||
notReadSlot.resize(slotcount, false);
|
||||
hasReadSlot.resize(slotcount, false);
|
||||
|
||||
// the height and width is written outside of specific format
|
||||
// so we create image first for it.
|
||||
@ -162,7 +162,7 @@ namespace LibCmo::CK2 {
|
||||
for (CKDWORD i = 0; i < slotcount; ++i) {
|
||||
CreateImage(width, height, i);
|
||||
if (ReadSpecificFormatBitmap(chunk, GetImageDesc(i))) {
|
||||
notReadSlot[i] = true;
|
||||
hasReadSlot[i] = true;
|
||||
} else {
|
||||
ReleaseImage(i);
|
||||
}
|
||||
@ -175,7 +175,7 @@ namespace LibCmo::CK2 {
|
||||
chunk->ReadStruct(slotcount);
|
||||
|
||||
SetSlotCount(slotcount);
|
||||
notReadSlot.resize(slotcount, false);
|
||||
hasReadSlot.resize(slotcount, false);
|
||||
|
||||
// the height and width is read by raw data function self.
|
||||
// so we pass a cache variable to reader and do some modification
|
||||
@ -183,7 +183,7 @@ namespace LibCmo::CK2 {
|
||||
for (CKDWORD i = 0; i < slotcount; ++i) {
|
||||
VxMath::VxImageDescEx rawcache;
|
||||
if (ReadRawBitmap(chunk, &rawcache)) {
|
||||
notReadSlot[i] = true;
|
||||
hasReadSlot[i] = true;
|
||||
|
||||
// do upside down blit
|
||||
CreateImage(rawcache.GetWidth(), rawcache.GetHeight(), i);
|
||||
@ -197,12 +197,12 @@ namespace LibCmo::CK2 {
|
||||
chunk->ReadStruct(slotcount);
|
||||
|
||||
SetSlotCount(slotcount);
|
||||
notReadSlot.resize(slotcount, false);
|
||||
hasReadSlot.resize(slotcount, false);
|
||||
|
||||
// MARK: a rough implement because we do not support this identifier
|
||||
for (CKDWORD i = 0; i < slotcount; ++i) {
|
||||
if (ReadOldRawBitmap(chunk, GetImageDesc(i))) {
|
||||
notReadSlot[i] = true;
|
||||
hasReadSlot[i] = true;
|
||||
} else {
|
||||
ReleaseImage(i);
|
||||
}
|
||||
@ -224,7 +224,7 @@ namespace LibCmo::CK2 {
|
||||
chunk->ReadString(filename);
|
||||
if (filename.empty()) continue;
|
||||
|
||||
bool isNotLoaded = i >= notReadSlot.size() || notReadSlot[i];
|
||||
bool isNotLoaded = i >= hasReadSlot.size() || (!hasReadSlot[i]);
|
||||
if (isNotLoaded) {
|
||||
// if this image is not loaded.
|
||||
// try resolve its file name and load it.
|
||||
@ -399,6 +399,14 @@ namespace LibCmo::CK2 {
|
||||
CKDWORD CKBitmapData::GetTransparentColor() {
|
||||
return m_TransColor;
|
||||
}
|
||||
|
||||
void CKBitmapData::SetPickThreshold(CKDWORD threshold) {
|
||||
m_PickThreshold = threshold;
|
||||
}
|
||||
|
||||
CKDWORD CKBitmapData::GetPickThreshold() {
|
||||
return m_PickThreshold;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
@ -114,12 +114,32 @@ namespace LibCmo::CK2 {
|
||||
See also: SetTranparentColor,SetTransparent
|
||||
*/
|
||||
CKDWORD GetTransparentColor();
|
||||
/**
|
||||
Summary: Sets pick threshold value.
|
||||
Arguments:
|
||||
pt: Pick threshold value to be set.
|
||||
Remarks:
|
||||
+ The pick threshold is used when picking object with
|
||||
transparent textures.
|
||||
+ It is the minimum value for alpha component
|
||||
below which picking is not valid.So this value is supposed to be in the range 0..255
|
||||
and the default value 0 means the picking is always valid.
|
||||
+ But if a value >0 is used and the texture use transparency (some pixels of the bitmap will have
|
||||
alpha component of 0) an object will not be picked on its transparent part.
|
||||
|
||||
See Also: CKRenderContext::Pick
|
||||
*/
|
||||
void SetPickThreshold(CKDWORD threshold);
|
||||
/**
|
||||
Summary: Gets pick threshold value.
|
||||
*/
|
||||
CKDWORD GetPickThreshold();
|
||||
|
||||
protected:
|
||||
CKContext* m_Context;
|
||||
XContainer::XArray<CKBitmapSlot> m_Slots;
|
||||
CKDWORD m_CurrentSlot;
|
||||
CKINT m_PickThreshold;
|
||||
CKDWORD m_PickThreshold;
|
||||
CK_BITMAPDATA_FLAGS m_BitmapFlags;
|
||||
CKDWORD m_TransColor;
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "ObjImpls/CKRenderObject.hpp"
|
||||
#include "ObjImpls/CK3dEntity.hpp"
|
||||
#include "ObjImpls/CK3dObject.hpp"
|
||||
#include "ObjImpls/CKTexture.hpp"
|
||||
|
||||
namespace LibCmo::CK2 {
|
||||
|
||||
@ -270,6 +271,7 @@ CKClassRegister(cid, parentCid, \
|
||||
EasyClassReg(ObjImpls::CKRenderObject, CK_CLASSID::CKCID_RENDEROBJECT, CK_CLASSID::CKCID_BEOBJECT, "Render Object");
|
||||
EasyClassReg(ObjImpls::CK3dEntity, CK_CLASSID::CKCID_3DENTITY, CK_CLASSID::CKCID_RENDEROBJECT, "3D Entity");
|
||||
EasyClassReg(ObjImpls::CK3dObject, CK_CLASSID::CKCID_3DOBJECT, CK_CLASSID::CKCID_3DENTITY, "3D Object");
|
||||
EasyClassReg(ObjImpls::CKTexture, CK_CLASSID::CKCID_TEXTURE, CK_CLASSID::CKCID_BEOBJECT, "Texture");
|
||||
|
||||
#undef EasyClassReg
|
||||
|
||||
|
@ -282,7 +282,7 @@ namespace LibCmo::CK2::DataHandlers {
|
||||
}
|
||||
|
||||
std::unique_ptr<CKBitmapHandler, CKBitmapHandlerDeleter> CKBitmapHandler::GetBitmapHandlerWrapper(const CKFileExtension& ext, const CKGUID& guid) {
|
||||
return std::unique_ptr<CKBitmapHandler, std::function<void(CKBitmapHandler*)>>(GetBitmapHandler(ext, guid));
|
||||
return std::unique_ptr<CKBitmapHandler, CKBitmapHandlerDeleter>(GetBitmapHandler(ext, guid));
|
||||
}
|
||||
|
||||
void CKBitmapHandlerDeleter::operator()(CKBitmapHandler* handler) {
|
||||
|
@ -3,7 +3,63 @@
|
||||
|
||||
namespace LibCmo::CK2::ObjImpls {
|
||||
|
||||
CKTexture::CKTexture(CKContext* ctx, CK_ID ckid, CKSTRING name) {}
|
||||
/**
|
||||
* @brief A fake struct define.
|
||||
* This define is served for a buffer read / write in CKTexture.
|
||||
* Because Virtools directly write a raw struct into file,
|
||||
* and our defines are different with Virtools.
|
||||
* So we need create a fake struct.
|
||||
*/
|
||||
struct FakeBitmapProperties {
|
||||
CKINT m_Size;
|
||||
struct {
|
||||
// fake CKGUID
|
||||
CKDWORD d1, d2;
|
||||
}m_ReaderGuid;
|
||||
struct {
|
||||
// fake CKFileExtension
|
||||
CKCHAR m_Data[4];
|
||||
}m_Ext;
|
||||
struct {
|
||||
// fake VxImageDescEx
|
||||
CK2::CKINT Size; ///< Size of the structure
|
||||
CK2::CKDWORD Flags; ///< Reserved for special formats (such as compressed ) 0 otherwise
|
||||
|
||||
CK2::CKINT Width; ///< Width in pixel of the image
|
||||
CK2::CKINT Height; ///< Height in pixel of the image
|
||||
union {
|
||||
CK2::CKINT BytesPerLine; ///< Pitch (width in bytes) of the image
|
||||
CK2::CKINT TotalImageSize; ///< For compressed image (DXT1...) the total size of the image
|
||||
};
|
||||
CK2::CKINT BitsPerPixel; ///< Number of bits per pixel
|
||||
union {
|
||||
CK2::CKDWORD RedMask; ///< Mask for Red component
|
||||
CK2::CKDWORD BumpDuMask; ///< Mask for Bump Du component
|
||||
};
|
||||
union {
|
||||
CK2::CKDWORD GreenMask; ///< Mask for Green component
|
||||
CK2::CKDWORD BumpDvMask; ///< Mask for Bump Dv component
|
||||
};
|
||||
union {
|
||||
CK2::CKDWORD BlueMask; ///< Mask for Blue component
|
||||
CK2::CKDWORD BumpLumMask; ///< Mask for Luminance component
|
||||
|
||||
};
|
||||
CK2::CKDWORD AlphaMask; ///< Mask for Alpha component
|
||||
|
||||
CK2::CKWORD BytesPerColorEntry; ///< ColorMap Stride
|
||||
CK2::CKWORD ColorMapEntries; ///< If other than 0 image is palletized
|
||||
|
||||
CK2::CKBYTE* ColorMap; ///< Palette colors
|
||||
CK2::CKBYTE* Image; ///< Image
|
||||
}m_Format;
|
||||
void* m_Data;
|
||||
};
|
||||
|
||||
CKTexture::CKTexture(CKContext* ctx, CK_ID ckid, CKSTRING name) :
|
||||
CKBeObject(ctx, ckid, name),
|
||||
m_ImageHost(ctx),
|
||||
m_VideoFormat(VxMath::VX_PIXELFORMAT::_16_ARGB1555), m_UseMipMap(false), m_MipmapImages() {}
|
||||
|
||||
CKTexture::~CKTexture() {}
|
||||
|
||||
@ -18,6 +74,118 @@ namespace LibCmo::CK2::ObjImpls {
|
||||
bool suc = CKBeObject::Load(chunk, file);
|
||||
if (!suc) return false;
|
||||
|
||||
// read base image
|
||||
suc = m_ImageHost.ReadFromChunk(chunk, file, CKBitmapDataReadIdentifiers {
|
||||
.m_SpecificFormat = static_cast<CKDWORD>(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXREADER),
|
||||
.m_RawData = static_cast<CKDWORD>(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXCOMPRESSED),
|
||||
.m_OldRawData = static_cast<CKDWORD>(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXBITMAPS),
|
||||
.m_FileNames = static_cast<CKDWORD>(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXFILENAMES),
|
||||
.m_MovieFileName = static_cast<CKDWORD>(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXAVIFILENAME)
|
||||
});
|
||||
if (!suc) return false;
|
||||
|
||||
if (chunk->GetDataVersion() < CK_STATECHUNK_DATAVERSION::CHUNK_MAJORCHANGE_VERSION) {
|
||||
// MARK: old data process. i don't want to process it anymore.
|
||||
// thus return false directly.
|
||||
return false;
|
||||
} else {
|
||||
CKDWORD fmtbytesize;
|
||||
if (chunk->SeekIdentifierAndReturnSize(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_OLDTEXONLY, &fmtbytesize)) {
|
||||
// 0xFF (blank) 0xFF (save options) 0xFF (transparent + movie info + video fmt) 0xFF (mip map)
|
||||
CKDWORD mixdata;
|
||||
chunk->ReadStruct(mixdata);
|
||||
m_UseMipMap = (mixdata & 0xFF);
|
||||
m_ImageHost.SetSaveOptions(static_cast<CK_TEXTURE_SAVEOPTIONS>((mixdata & 0xFF0000) >> 16));
|
||||
|
||||
mixdata = mixdata & 0xFF00 >> 8;
|
||||
m_ImageHost.SetTransparent(mixdata & 0x1);
|
||||
bool hasVideoFmt = mixdata & 0x2;
|
||||
// MARK: I ignore 0x4 in there because it involve video.
|
||||
|
||||
// set current slot, transparent color, and video format.
|
||||
CKDWORD currentSlot, transColor, videoFmt;
|
||||
fmtbytesize -= CKSizeof(CKDWORD);
|
||||
switch (fmtbytesize) {
|
||||
case (3 * sizeof(CKDWORD)):
|
||||
chunk->ReadStruct(transColor);
|
||||
m_ImageHost.SetTransparentColor(transColor);
|
||||
chunk->ReadStruct(currentSlot);
|
||||
m_ImageHost.SetCurrentSlot(currentSlot);
|
||||
chunk->ReadStruct(m_VideoFormat);
|
||||
break;
|
||||
case (2 * sizeof(CKDWORD)):
|
||||
if (m_ImageHost.GetSlotCount() <= 1 || !hasVideoFmt) {
|
||||
chunk->ReadStruct(transColor);
|
||||
m_ImageHost.SetTransparentColor(transColor);
|
||||
}
|
||||
if (m_ImageHost.GetSlotCount() > 1) {
|
||||
chunk->ReadStruct(currentSlot);
|
||||
m_ImageHost.SetCurrentSlot(currentSlot);
|
||||
}
|
||||
if (hasVideoFmt) {
|
||||
chunk->ReadStruct(m_VideoFormat);
|
||||
}
|
||||
break;
|
||||
case (sizeof(CKDWORD)):
|
||||
if (hasVideoFmt) {
|
||||
chunk->ReadStruct(m_VideoFormat);
|
||||
} else if (m_ImageHost.GetSlotCount() <= 1) {
|
||||
chunk->ReadStruct(transColor);
|
||||
m_ImageHost.SetTransparentColor(transColor);
|
||||
} else {
|
||||
chunk->ReadStruct(currentSlot);
|
||||
m_ImageHost.SetCurrentSlot(currentSlot);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// read mipmap
|
||||
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_USERMIPMAP)) {
|
||||
CKDWORD mipmapCount;
|
||||
chunk->ReadStruct(mipmapCount);
|
||||
m_MipmapImages.resize(mipmapCount);
|
||||
|
||||
for (CKDWORD i = 0; i < mipmapCount; ++i) {
|
||||
VxMath::VxImageDescEx cache;
|
||||
if (CKBitmapData::ReadRawBitmap(chunk, &cache)) {
|
||||
VxMath::VxDoBlitUpsideDown(&cache, &m_MipmapImages[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// pick threshold
|
||||
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_PICKTHRESHOLD)) {
|
||||
CKDWORD threshold;
|
||||
chunk->ReadStruct(threshold);
|
||||
m_ImageHost.SetPickThreshold(threshold);
|
||||
}
|
||||
|
||||
// save properties
|
||||
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_TEXTURE::CK_STATESAVE_TEXSAVEFORMAT)) {
|
||||
CKDWORD bufsize;
|
||||
CKStateChunk::TBuffer buf;
|
||||
chunk->ReadBufferWrapper(&buf, &bufsize);
|
||||
if (buf != nullptr) {
|
||||
FakeBitmapProperties* props = reinterpret_cast<FakeBitmapProperties*>(buf.get());
|
||||
|
||||
CKBitmapProperties myprops(
|
||||
CKGUID(props->m_ReaderGuid.d1, props->m_ReaderGuid.d2),
|
||||
props->m_Ext.m_Data
|
||||
);
|
||||
m_ImageHost.SetSaveFormat(myprops);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// correct video format
|
||||
if (m_VideoFormat > VxMath::VX_PIXELFORMAT::_32_X8L8V8U8) {
|
||||
m_VideoFormat = VxMath::VX_PIXELFORMAT::_16_ARGB1555;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||
CKBitmapData m_ImageHost;
|
||||
VxMath::VX_PIXELFORMAT m_VideoFormat;
|
||||
bool m_UseMipMap;
|
||||
XContainer::XArray<VxMath::VxImageDescEx> m_MipmapImages;
|
||||
};
|
||||
|
||||
//class CKRenderObject : public CKBeObject {
|
||||
|
Reference in New Issue
Block a user