Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 174 additions & 28 deletions Engine/source/T3D/assets/ImageAsset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "gfx/gfxStringEnumTranslate.h"

#include "ImageAssetInspectors.h"
#include "core/stream/memStream.h"

// Debug Profiling.
#include "platform/profiler.h"
Expand Down Expand Up @@ -150,12 +151,17 @@ ImageAsset::ImageAsset() :
mIsHDRImage(false),
mImageType(Albedo),
mIsNamedTarget(false),
mIsDDS(false),
mImageWidth(-1),
mImageHeight(-1),
mImageDepth(-1),
mImageChannels(-1)
mImageChannels(-1),
mCellCountX(1),
mCellCountY(1)
{
mEmbeddedBitmap = NULL;
mLoadedState = AssetErrCode::NotLoaded;
VECTOR_SET_ASSOCIATION(mFrames);
}

//-----------------------------------------------------------------------------
Expand All @@ -169,6 +175,19 @@ ImageAsset::~ImageAsset()
}

mResourceMap.clear();

FrameTextureMap::iterator frameIter = mFrameTextureMap.begin();
for (; frameIter != mFrameTextureMap.end(); ++frameIter)
{
frameIter->value.free();
}

mFrameTextureMap.clear();

mFrames.clear();

if (mEmbeddedBitmap)
delete mEmbeddedBitmap;
}


Expand Down Expand Up @@ -201,6 +220,9 @@ void ImageAsset::initPersistFields()
addProtectedField("isHDRImage", TypeBool, Offset(mIsHDRImage, ImageAsset), &setTextureHDR, &defaultProtectedGetFn, &writeTextureHDR, "HDR Image?");

addField("imageType", TypeImageAssetType, Offset(mImageType, ImageAsset), "What the main use-case for the image is for.");

addField("cellCountX", TypeS32, Offset(mCellCountX, ImageAsset), "Number of cells along the X axis.");
addField("cellCountY", TypeS32, Offset(mCellCountY, ImageAsset), "Number of cells along the Y axis.");
}
bool ImageAsset::onAdd()
{
Expand Down Expand Up @@ -435,6 +457,12 @@ U32 ImageAsset::load()
if (mLoadedState == Ok)
return mLoadedState;

if (mEmbeddedBitmap)
{
mLoadedState = Ok;
return mLoadedState;
}

if (!Torque::FS::IsFile(mImageFile))
{
if (isNamedTarget())
Expand Down Expand Up @@ -491,6 +519,18 @@ GFXTexHandle ImageAsset::getTexture(GFXTextureProfile* requestedProfile)

if (mLoadedState == Ok)
{
if (mEmbeddedBitmap)
{
GFXTexHandle newTex;
newTex.set(mEmbeddedBitmap, requestedProfile, false, avar("%s %s() - mTextureObject (line %d)", mImageFile, __FUNCTION__, __LINE__));
if (newTex)
{
mResourceMap.insert(requestedProfile, newTex);
return newTex;
}
}
else
{
//If we don't have an existing map case to the requested format, we'll just create it and insert it in
GFXTexHandle newTex;
newTex.set(mImageFile, requestedProfile, avar("%s %s() - mTextureObject (line %d)", mImageFile, __FUNCTION__, __LINE__));
Expand All @@ -499,6 +539,7 @@ GFXTexHandle ImageAsset::getTexture(GFXTextureProfile* requestedProfile)
mResourceMap.insert(requestedProfile, newTex);
return newTex;
}
}
}

return nullptr;
Expand Down Expand Up @@ -600,6 +641,52 @@ void ImageAsset::onTamlCustomWrite(TamlCustomNodes& customNodes)
pImageInfoNode->addField(StringTable->insert("ImageHeight"), mImageHeight);
pImageInfoNode->addField(StringTable->insert("ImageDepth"), mImageDepth);

if (gEmbedAssetData)
{
GBitmap* image = NULL;
Torque::Path path = expandAssetFilePath(mImageFile);
if (mIsDDS)
{
Resource<DDSFile> dds = DDSFile::load(path, 0);
if (dds != NULL)
{
image = new GBitmap();
if (!dds->decompressToGBitmap(image))
{
delete image;
image = NULL;
}
}
}
else
{
Resource<GBitmap> resImage = GBitmap::load(path);
if(resImage)
image = new GBitmap(*resImage);
}

if (!image)
return;

path.setExtension("dbm");

FileStream stream;
if (!stream.open(path, Torque::FS::File::Write))
{
Con::errorf("ImageAsset::onTamlCustomWrite failed to open cache path %s", path.getFullFileName().c_str());
stream.close();
delete image;
return;
}

image->write(stream);
stream.close();

delete image;

pImageInfoNode->addField(StringTable->insert("BitmapCache"), path.getFullPath().c_str());
}

}

void ImageAsset::onTamlCustomRead(const TamlCustomNodes& customNodes)
Expand Down Expand Up @@ -636,6 +723,20 @@ void ImageAsset::onTamlCustomRead(const TamlCustomNodes& customNodes)
{
pField->getFieldValue(mImageDepth);
}
else if (fieldName == StringTable->insert("BitmapCache"))
{
Torque::Path path = pField->getFieldValue();

if (Torque::FS::IsFile(path))
{
FileStream stream;
if (stream.open(path, Torque::FS::File::Read))
{
mEmbeddedBitmap = new GBitmap;
mEmbeddedBitmap->read(stream);
}
}
}
else
{
// Unknown name so warn.
Expand All @@ -648,44 +749,59 @@ void ImageAsset::onTamlCustomRead(const TamlCustomNodes& customNodes)

void ImageAsset::populateImage(void)
{
if (Torque::FS::IsFile(mImageFile))
if (mEmbeddedBitmap == NULL)
{
if (dStrEndsWith(mImageFile, ".dds"))
if (Torque::FS::IsFile(mImageFile))
{
DDSFile* tempFile = new DDSFile();
FileStream* ddsFs;
if ((ddsFs = FileStream::createAndOpen(mImageFile, Torque::FS::File::Read)) == NULL)
if (dStrEndsWith(mImageFile, ".dds"))
{
Con::errorf("ImageAsset::setImageFile Failed to open ddsfile: %s", mImageFile);
}
DDSFile* tempFile = new DDSFile();
FileStream* ddsFs;
if ((ddsFs = FileStream::createAndOpen(mImageFile, Torque::FS::File::Read)) == NULL)
{
Con::errorf("ImageAsset::populateImage Failed to open ddsfile: %s", mImageFile);
}

if (!tempFile->readHeader(*ddsFs))
{
Con::errorf("ImageAsset::setImageFile Failed to read header of ddsfile: %s", mImageFile);
if (!tempFile->readHeader(*ddsFs))
{
Con::errorf("ImageAsset::populateImage Failed to read header of ddsfile: %s", mImageFile);
}
else
{
mImageWidth = tempFile->mWidth;
mImageHeight = tempFile->mHeight;
}

ddsFs->close();
delete tempFile;
mIsDDS = true;
}
else
{
mImageWidth = tempFile->mWidth;
mImageHeight = tempFile->mHeight;
}
if (dStrEndsWith(mImageFile, ".ies"))
{
return;
}

ddsFs->close();
delete tempFile;
}
else
{
if (!stbi_info(mImageFile, &mImageWidth, &mImageHeight, &mImageChannels))
{
StringTableEntry stbErr = stbi_failure_reason();
if (stbErr == StringTable->EmptyString())
stbErr = "ImageAsset::Unkown Error!";
if (!stbi_info(mImageFile, &mImageWidth, &mImageHeight, &mImageChannels))
{
StringTableEntry stbErr = stbi_failure_reason();
if (stbErr == StringTable->EmptyString())
stbErr = "ImageAsset::Unkown Error!";

Con::errorf("ImageAsset::setImageFile STB Get file info failed: %s", stbErr);
Con::errorf("ImageAsset::populateImage STB Get file info failed: %s", stbErr);
}
}
}

// we only support 2d textures..... for now ;)
mImageDepth = 1;
// we only support 2d textures..... for now ;)
mImageDepth = 1;

generateFrames();
}
}
else // we have an embedded bitmap, just generate frames.
{
generateFrames();
}
}

Expand Down Expand Up @@ -713,6 +829,36 @@ const char* ImageAsset::getImageInfo()
return "";
}

void ImageAsset::generateFrames(void)
{
mFrames.clear();

const F32 texelWidthScale = 1.0f / (F32)mImageWidth;
const F32 texelHeightScale = 1.0f / (F32)mImageHeight;

// mFrames zero is always the full image.
mFrames.push_back(Frame(0, 0,
mImageWidth, mImageHeight,
texelWidthScale, texelHeightScale));

if (mCellCountX <= 1 && mCellCountY <= 1)
return;

const U32 cellWidth = mImageWidth / mCellCountX;
const U32 cellHeight = mImageHeight / mCellCountY;

for (U32 y = 0; y < mCellCountY; y++)
{
for (U32 x = 0; x < mCellCountX; x++)
{
mFrames.push_back(Frame(
x * cellWidth, y * cellHeight,
cellWidth, cellHeight,
texelWidthScale, texelHeightScale));
}
}
}

DefineEngineMethod(ImageAsset, getImagePath, const char*, (), ,
"Gets the image filepath of this asset.\n"
"@return File path of the image file.")
Expand Down
27 changes: 25 additions & 2 deletions Engine/source/T3D/assets/ImageAsset.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ class ImageAsset : public AssetBase

public:
typedef HashMap<GFXTextureProfile*, GFXTexHandle> ImageTextureMap;

typedef CompoundKey<U32, GFXTextureProfile*> FrameKey;
typedef HashMap<FrameKey, GFXTexHandle> FrameTextureMap;
/// The different types of image use cases
enum ImageTypes
{
Expand All @@ -83,13 +86,23 @@ class ImageAsset : public AssetBase
class Frame
{
public:
Frame()
: regionName(StringTable->EmptyString())
{
pixelOffset.set(0, 0);
pixelSize.set(0, 0);
texelLower.set(0.0f, 0.0f);
texelUpper.set(0.0f, 0.0f);
texelSize.set(0.0f, 0.0f);
}

Frame(const S32 pixelOffsetX, const S32 pixelOffsetY,
const U32 pixelWidth, const U32 pixelHeight,
const F32 texelWidthScale, const F32 texelHeightScale,
StringTableEntry inRegionName = StringTable->EmptyString())
: regionName(inRegionName)
{
pixelOffset.set(pixelOffsetY, pixelOffsetY);
pixelOffset.set(pixelOffsetX, pixelOffsetY);
pixelSize.set(pixelWidth, pixelHeight);

texelLower.set(pixelOffsetX * texelWidthScale, pixelOffsetY * texelHeightScale);
Expand Down Expand Up @@ -132,17 +145,24 @@ class ImageAsset : public AssetBase
return mErrCodeStrings[errCode - Parent::Extended];
};
private:

GBitmap* mEmbeddedBitmap;
StringTableEntry mImageFile;
bool mUseMips;
bool mIsHDRImage;
bool mIsDDS;
ImageTypes mImageType;
ImageTextureMap mResourceMap;
bool mIsNamedTarget;
S32 mImageWidth;
S32 mImageHeight;
S32 mImageDepth;
S32 mImageChannels;
U32 mCellCountX;
U32 mCellCountY;
Vector<Frame> mFrames;
FrameTextureMap mFrameTextureMap;

inline void clampFrame(U32& frame) const { const U32 totalFrames = mFrames.size(); if (frame >= totalFrames) frame = (totalFrames == 0 ? 0 : totalFrames - 1); };
public:
ImageAsset();
virtual ~ImageAsset();
Expand Down Expand Up @@ -191,13 +211,16 @@ class ImageAsset : public AssetBase
bool isNamedTarget(void) const { return mIsNamedTarget; }
NamedTexTargetRef getNamedTarget(void) const { return NamedTexTarget::find(mImageFile + 1); }

inline const Frame& getImageFrame(U32 frame) const { clampFrame(frame); return mFrames[frame]; };

static U32 getAssetByFilename(StringTableEntry fileName, AssetPtr<ImageAsset>* imageAsset);
static StringTableEntry getAssetIdByFilename(StringTableEntry fileName);
static U32 getAssetById(StringTableEntry assetId, AssetPtr<ImageAsset>* imageAsset);
static U32 getAssetById(String assetId, AssetPtr<ImageAsset>* imageAsset) { return getAssetById(assetId.c_str(), imageAsset); };

void populateImage(void);
const char* getImageInfo();
void generateFrames(void);

protected:
// Asset Base callback
Expand Down
2 changes: 1 addition & 1 deletion Engine/source/T3D/assets/assetImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ String AssetImporter::getAssetTypeByFile(Torque::Path filePath)
if (fileExt == String("dts") && fileName.endsWith("cached"))
return "";

if (fileExt == String("png") || fileExt == String("jpg") || fileExt == String("jpeg") || fileExt == String("dds"))
if (fileExt == String("png") || fileExt == String("jpg") || fileExt == String("jpeg") || fileExt == String("bmp") || fileExt == String("hdr") || fileExt == String("dds") || fileExt == String("ies"))
return "ImageAsset";
else if (fileExt == String("dae") || fileExt == String("fbx") || fileExt == String("blend") || fileExt == String("obj") || fileExt == String("dts") || fileExt == String("gltf") || fileExt == String("glb"))
return "ShapeAsset";
Expand Down
Loading
Loading