Commit 3cacd365 by wester

Embedded Textures

parent d033a933
...@@ -2,11 +2,7 @@ ...@@ -2,11 +2,7 @@
#include "MasterTestProject.h" #include "MasterTestProject.h"
#include <time.h> #include <time.h>
#include "ImageUtils.h"
#include "ImageWrapper.h" //requires "ImageWrapper" in public dependencies in build CS
#include "ProceduralEntity.h" #include "ProceduralEntity.h"
#include "Runtime/Engine/Public/DDSLoader.h"
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/Logger.hpp> #include <assimp/Logger.hpp>
...@@ -258,6 +254,7 @@ UMaterialInterface *AProceduralEntity::GetMaterialForIndex(unsigned int index, ...@@ -258,6 +254,7 @@ UMaterialInterface *AProceduralEntity::GetMaterialForIndex(unsigned int index,
aiString Path; aiString Path;
if (AMat->GetTexture(aiTextureType_DIFFUSE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) { if (AMat->GetTexture(aiTextureType_DIFFUSE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) {
FString fileName = FString(Path.C_Str()); FString fileName = FString(Path.C_Str());
...@@ -270,162 +267,113 @@ UMaterialInterface *AProceduralEntity::GetMaterialForIndex(unsigned int index, ...@@ -270,162 +267,113 @@ UMaterialInterface *AProceduralEntity::GetMaterialForIndex(unsigned int index,
dirPath = temp; dirPath = temp;
} }
UE_LOG(GLTF, Warning, TEXT("Diffuse Texture:\"%s\" \"%s\""), *dirPath, *fileName);
UTexture2D* diffTexture = LoadTexture(dirPath, fileName);
bool isValid;
int32 width, height;
diffTexture = Victory_LoadTexture2D_FromFile(dirPath + "\\" + fileName, isValid, width, height);
newMaterial->SetTextureParameterValue(FName("DiffuseTexture"), diffTexture);
MaterialMap.Add(index, newMaterial);
}
else {
UE_LOG(GLTF, Warning, TEXT("No Diffuse Texture"));
}
}
return newMaterial;
}
}
/** Loads a texture from the data path */ if (Path.data[0] == '*') { //embedded
//https://drive.google.com/file/d/0BzqpBc4MrAMXLXN1ZGNzUEJZc1k/edit int32 textureIndex = FCString::Atoi(*fileName.RightChop(1));
//https://forums.unrealengine.com/showthread.php?33446-Creating-UTexture-from-data-in-code-making-it-a-material-and-adding-it-to-a-mesh //TODO "(note Atoi is unsafe; no way to indicate errors)" from Unreal Wiki
UTexture2D* AProceduralEntity::LoadTexture(FString Folder, FString FileName)
{
FString TexturePath = Folder + "\\" + FileName;
UTexture2D* Texture = NULL;
TArray<uint8> FileData; if (textureIndex >= 0) {
aiTexture *aiTexture = scene->mTextures[textureIndex];
/* Load DDS texture */ UE_LOG(GLTF, Warning, TEXT("Importing Texture with Index \"%s\" %d (%d|%d)"), *fileName, textureIndex, aiTexture->mWidth, aiTexture->mHeight);
if (FFileHelper::LoadFileToArray(FileData, *TexturePath, 0))
{
FDDSLoadHelper DDSLoadHelper(&FileData[0], FileData.Num());
if (DDSLoadHelper.IsValid2DTexture())
{
int32 NumMips = DDSLoadHelper.ComputeMipMapCount();
EPixelFormat Format = DDSLoadHelper.ComputePixelFormat();
int32 BlockSize = 16;
if (NumMips == 0) if (aiTexture->mHeight == 0) { // If mHeight = 0 this is a pointer to a memory buffer of size mWidth containing the compressed texture data. Good luck, have fun!
{ FString extension = FString(aiTexture->achFormatHint);
NumMips = 1; EImageFormat::Type format = GetImageTypeByExtension(extension);
}
if (Format == PF_DXT1) bool isValid;
{ int32 width, height;
BlockSize = 8; UTexture2D* diffTexture = LoadTexture2D((uint8*)aiTexture->pcData, aiTexture->mWidth, format, isValid, width, height);
}
/* Create transient texture */ if (isValid)
Texture = UTexture2D::CreateTransient(DDSLoadHelper.DDSHeader->dwWidth, DDSLoadHelper.DDSHeader->dwHeight, Format); newMaterial->SetTextureParameterValue(FName("DiffuseTexture"), diffTexture);
Texture->MipGenSettings = TMGS_LeaveExistingMips;
Texture->PlatformData->NumSlices = 1;
Texture->NeverStream = true;
Texture->Rename(*FileName);
/* Get pointer to actual data */
uint8* DataPtr = (uint8*)DDSLoadHelper.GetDDSDataPointer();
uint32 CurrentWidth = DDSLoadHelper.DDSHeader->dwWidth;
uint32 CurrentHeight = DDSLoadHelper.DDSHeader->dwHeight;
/* Iterate through mips */
for (int32 i = 0; i < NumMips; i++)
{
/* Lock to 1x1 as smallest size */
CurrentWidth = (CurrentWidth < 1) ? 1 : CurrentWidth;
CurrentHeight = (CurrentHeight < 1) ? 1 : CurrentHeight;
/* Get number of bytes to read */
int32 NumBytes = CurrentWidth * CurrentHeight * 4;
if (Format == PF_DXT1 || Format == PF_DXT3 || Format == PF_DXT5)
{
/* Compressed formats */
NumBytes = ((CurrentWidth + 3) / 4) * ((CurrentHeight + 3) / 4) * BlockSize;
}
/* Write to existing mip */ }
if (i < Texture->PlatformData->Mips.Num()) else {
{ //TODO not implemented
FTexture2DMipMap& Mip = Texture->PlatformData->Mips[i]; UE_LOG(GLTF, Error, TEXT("not Implemented Texture Format"));
}
}
else {
UE_LOG(GLTF, Error, TEXT("Invalid Texture Index \"%s\""), *fileName);
}
void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);
FMemory::Memcpy(Data, DataPtr, NumBytes);
Mip.BulkData.Unlock();
} }
else {
UE_LOG(GLTF, Warning, TEXT("Diffuse Texture:\"%s\" \"%s\" %d"), *dirPath, *fileName, Path.length);
bool isValid;
int32 width, height;
UTexture2D* diffTexture = LoadTexture2D_FromFile(dirPath + "\\" + fileName, isValid, width, height);
/* Add new mip */ if (isValid)
else newMaterial->SetTextureParameterValue(FName("DiffuseTexture"), diffTexture);
{
FTexture2DMipMap* Mip = new(Texture->PlatformData->Mips) FTexture2DMipMap();
Mip->SizeX = CurrentWidth;
Mip->SizeY = CurrentHeight;
Mip->BulkData.Lock(LOCK_READ_WRITE);
Mip->BulkData.Realloc(NumBytes);
Mip->BulkData.Unlock();
void* Data = Mip->BulkData.Lock(LOCK_READ_WRITE);
FMemory::Memcpy(Data, DataPtr, NumBytes);
Mip->BulkData.Unlock();
} }
/* Set next mip level */
CurrentWidth /= 2;
CurrentHeight /= 2;
DataPtr += NumBytes;
MaterialMap.Add(index, newMaterial);
}
else {
UE_LOG(GLTF, Warning, TEXT("No Diffuse Texture"));
} }
Texture->UpdateResource();
} }
}
return Texture;
}
//https://wiki.unrealengine.com/Rama%27s_Vertex_Snap_Editor_Plugin#Plugin_Download
UTexture2D* AProceduralEntity::Victory_LoadTexture2D_FromFile(const FString& FullFilePath, bool& IsValid, int32& Width, int32& Height) return newMaterial;
{ }
IsValid = false; }
UTexture2D* LoadedT2D = NULL;
EImageFormat::Type format = EImageFormat::JPEG;
FString extension = FPaths::GetExtension(FullFilePath);
EImageFormat::Type AProceduralEntity::GetImageTypeByExtension(const FString& extension) {
EImageFormat::Type format = EImageFormat::Invalid;
if (extension.EndsWith(TEXT("jpg"), ESearchCase::IgnoreCase)) { if (extension.EndsWith(TEXT("jpg"), ESearchCase::IgnoreCase)) {
format = EImageFormat::JPEG; format = EImageFormat::JPEG;
} else if (extension.EndsWith(TEXT("png"), ESearchCase::IgnoreCase)) { }
else if (extension.EndsWith(TEXT("png"), ESearchCase::IgnoreCase)) {
format = EImageFormat::PNG; format = EImageFormat::PNG;
} else if (extension.EndsWith(TEXT("bmp"), ESearchCase::IgnoreCase)) { }
else if (extension.EndsWith(TEXT("bmp"), ESearchCase::IgnoreCase)) {
format = EImageFormat::BMP; format = EImageFormat::BMP;
} else if (extension.EndsWith(TEXT("ico"), ESearchCase::IgnoreCase)) { }
else if (extension.EndsWith(TEXT("ico"), ESearchCase::IgnoreCase)) {
format = EImageFormat::ICO; format = EImageFormat::ICO;
} else if (extension.EndsWith(TEXT("exr"), ESearchCase::IgnoreCase)) { }
else if (extension.EndsWith(TEXT("exr"), ESearchCase::IgnoreCase)) {
format = EImageFormat::EXR; format = EImageFormat::EXR;
}else if (extension.EndsWith(TEXT("icns"), ESearchCase::IgnoreCase)) { }
else if (extension.EndsWith(TEXT("icns"), ESearchCase::IgnoreCase)) {
format = EImageFormat::ICNS; format = EImageFormat::ICNS;
} }
return format;
}
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper(format); //https://wiki.unrealengine.com/Rama%27s_Vertex_Snap_Editor_Plugin#Plugin_Download
UTexture2D* AProceduralEntity::LoadTexture2D_FromFile(const FString& FullFilePath, bool& IsValid, int32& Width, int32& Height)
{
EImageFormat::Type format = GetImageTypeByExtension(FPaths::GetExtension(FullFilePath));
//Load From File //Load From File
TArray<uint8> RawFileData; TArray<uint8> RawFileData;
if (!FFileHelper::LoadFileToArray(RawFileData, *FullFilePath)) return NULL; if (!FFileHelper::LoadFileToArray(RawFileData, *FullFilePath)) return NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return LoadTexture2D(RawFileData.GetData(), RawFileData.Num(), format, IsValid, Width, Height);
}
UTexture2D* AProceduralEntity::LoadTexture2D(uint8* RawFileData, int32 lenght, EImageFormat::Type Format, bool& IsValid, int32& Width, int32& Height) {
IsValid = false;
UTexture2D* LoadedT2D = NULL;
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper(Format);
//Create T2D! //Create T2D!
if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(RawFileData.GetData(), RawFileData.Num())) if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(RawFileData, lenght))
{ {
const TArray<uint8>* UncompressedBGRA = NULL; const TArray<uint8>* UncompressedBGRA = NULL;
if (ImageWrapper->GetRaw(ERGBFormat::BGRA, 8, UncompressedBGRA)) if (ImageWrapper->GetRaw(ERGBFormat::BGRA, 8, UncompressedBGRA))
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/postprocess.h> #include <assimp/postprocess.h>
#include "ImageUtils.h"
#include "ImageWrapper.h" //requires "ImageWrapper" in public dependencies in build CS
#include "GameFramework/Actor.h" #include "GameFramework/Actor.h"
#include "ProceduralMeshComponent.h" #include "ProceduralMeshComponent.h"
#include "ProceduralEntity.generated.h" #include "ProceduralEntity.generated.h"
...@@ -77,7 +80,9 @@ private: ...@@ -77,7 +80,9 @@ private:
void processNode(aiNode* node, const aiScene* scene); void processNode(aiNode* node, const aiScene* scene);
void loadModel(std::string path); void loadModel(std::string path);
UMaterialInterface *GetMaterialForIndex(unsigned int index, const aiScene* scene); UMaterialInterface *GetMaterialForIndex(unsigned int index, const aiScene* scene);
UTexture2D* LoadTexture(FString Folder, FString FileName);
UTexture2D* Victory_LoadTexture2D_FromFile(const FString& FullFilePath, bool& IsValid, int32& Width, int32& Height); UTexture2D* LoadTexture2D_FromFile(const FString& FullFilePath, bool& IsValid, int32& Width, int32& Height);
UTexture2D* LoadTexture2D(uint8* RawFileData, int32 lenght, EImageFormat::Type Format, bool& IsValid, int32& Width, int32& Height);
EImageFormat::Type GetImageTypeByExtension(const FString& extension);
}; };
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment