Commit 15fb776a by wester

Merge branch 'Assimp' of ssh://git.breab.org:2223/kai/MasterTestProjekt into Assimp

# Conflicts: # Content/MobileStarterContent/Maps/Minimal_Default.umap # Content/MobileStarterContent/Maps/Minimal_Default_BuiltData.uasset # Source/MasterTestProject/ue4-assimp/ProceduralEntity.cpp
parents 8495d8c4 113e3ce1
......@@ -4,6 +4,8 @@
#include "ProceduralEntity.h"
#include "Runtime/Engine/Public/DDSLoader.h"
#include "VictoryBPFunctionLibrary.h"
#include <assimp/DefaultLogger.hpp>
#include <assimp/Logger.hpp>
......@@ -46,7 +48,7 @@ void AProceduralEntity::PostActorCreated() {
Super::PostActorCreated();
if (!IsTemplate(RF_Transient)) {
UE_LOG(LogTemp, Warning, TEXT("Fiel Path: %s"), *_filePath);
UE_LOG(GLTF, Warning, TEXT("Fiel Path: %s"), *_filePath);
std::string filename(TCHAR_TO_UTF8(*_filePath));
loadModel(filename);
}
......@@ -63,24 +65,25 @@ void AProceduralEntity::Tick(float DeltaTime)
// quick C++11 trick to get a char * from a std::string
char* filename = &sfilename[0];
result = _stat(filename, &buf);
if (result != 0) {
UE_LOG(LogTemp, Warning, TEXT("Problem getting info"));
UE_LOG(GLTF, Warning, TEXT("Problem getting info"));
switch (errno) {
case ENOENT:
UE_LOG(LogTemp, Warning, TEXT("File not found."));
UE_LOG(GLTF, Warning, TEXT("File not found."));
break;
case EINVAL:
UE_LOG(LogTemp, Warning, TEXT("Invalid parameter to _stat."));
UE_LOG(GLTF, Warning, TEXT("Invalid parameter to _stat."));
break;
default:
UE_LOG(LogTemp, Warning, TEXT("Unexpected error."));
UE_LOG(GLTF, Warning, TEXT("Unexpected error."));
}
}
else {
if (_lastModifiedTime == 0 || (int)buf.st_mtime > _lastModifiedTime) {
_lastModifiedTime = (int)buf.st_mtime;
UE_LOG(LogTemp, Warning, TEXT("Reloading model. %s"), *_filePath);
UE_LOG(GLTF, Warning, TEXT("Reloading model. %s"), *_filePath);
loadModel(sfilename);
}
}
......@@ -93,7 +96,7 @@ void AProceduralEntity::loadModelFromBlueprint() {
/* ASSIMP IMPORT */
void AProceduralEntity::processMesh(aiMesh* mesh, const aiScene* scene) {
UE_LOG(LogTemp, Warning, TEXT("Processing mesh"));
UE_LOG(GLTF, Warning, TEXT("Processing mesh"));
// the very first time this method runs, we'll need to create the empty arrays
// we can't really do that in the class constructor because we don't know how many meshes we'll read, and this data can change between imports
......@@ -159,25 +162,31 @@ void AProceduralEntity::processMesh(aiMesh* mesh, const aiScene* scene) {
// we can finally either update or create the mesh
if (_requiresFullRecreation) {
UE_LOG(LogTemp, Warning, TEXT("Full recreation"));
UE_LOG(GLTF, Warning, TEXT("Full recreation"));
_mesh->CreateMeshSection(_meshCurrentlyProcessed, _vertices[_meshCurrentlyProcessed], _indices[_meshCurrentlyProcessed], _normals[_meshCurrentlyProcessed], _uvs[_meshCurrentlyProcessed], _vertexColors[_meshCurrentlyProcessed], _tangents[_meshCurrentlyProcessed], true);
}
else {
UE_LOG(LogTemp, Warning, TEXT("Update"));
UE_LOG(GLTF, Warning, TEXT("Update"));
_mesh->UpdateMeshSection(_meshCurrentlyProcessed, _vertices[_meshCurrentlyProcessed], _normals[_meshCurrentlyProcessed], _uvs[_meshCurrentlyProcessed], _vertexColors[_meshCurrentlyProcessed], _tangents[_meshCurrentlyProcessed]);
}
UE_LOG(LogTemp, Warning, TEXT("Done creating the mesh"));
//load material
UMaterialInterface *material = GetMaterialForIndex(mesh->mMaterialIndex, scene);
_mesh->SetMaterial(_meshCurrentlyProcessed, material);
UE_LOG(GLTF, Warning, TEXT("Done creating the mesh"));
_requiresFullRecreation = false;
}
void AProceduralEntity::processNode(aiNode* node, const aiScene* scene) {
UE_LOG(LogTemp, Warning, TEXT("Processing a node"));
UE_LOG(GLTF, Warning, TEXT("Processing a node"));
// process all the node's meshes
for (uint32 i = 0; i < node->mNumMeshes; i++) {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
UE_LOG(LogTemp, Warning, TEXT("New mesh in the node %i"), mesh->mNumVertices);
UE_LOG(GLTF, Warning, TEXT("New mesh in the node %i"), mesh->mNumVertices);
_numVertecies += mesh->mNumVertices;
processMesh(mesh, scene);
++_meshCurrentlyProcessed;
......@@ -185,7 +194,7 @@ void AProceduralEntity::processNode(aiNode* node, const aiScene* scene) {
// do the same for all of its children
for (uint32 i = 0; i < node->mNumChildren; i++) {
UE_LOG(LogTemp, Warning, TEXT("New child in the node"));
UE_LOG(GLTF, Warning, TEXT("New child in the node"));
processNode(node->mChildren[i], scene);
}
}
......@@ -193,28 +202,237 @@ void AProceduralEntity::processNode(aiNode* node, const aiScene* scene) {
void AProceduralEntity::loadModel(std::string path) {
Assimp::Importer importer;
UE_LOG(LogTemp, Warning, TEXT("START LOGGING"));
UE_LOG(GLTF, Warning, TEXT("START LOGGING"));
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_GenNormals);
if (!scene) {
UE_LOG(GLTF, Error, TEXT("Failed, Scene is empty: %s"), *FString(importer.GetErrorString()));
UE_LOG(LogTemp, Error, TEXT("Failed, Scene is empty: %s"), *FString(importer.GetErrorString()));
std::string extensions;
importer.GetExtensionList(extensions);
UE_LOG(GLTF, Error, TEXT("Extension list: %s"), *FString(extensions.c_str()));
UE_LOG(LogTemp, Error, TEXT("Extension list: %s"), *FString(extensions.c_str()));
wchar_t buffer[260];
GetModuleFileName(NULL, buffer, MAX_PATH);
UE_LOG(GLTF, Error, TEXT("Curretn PAth: %s"), *FString(buffer));
return;
}
double start = FPlatformTime::Seconds();
UE_LOG(GLTF, Warning, TEXT("Has MAterials: %s"), scene->HasMaterials() ? TEXT("True") : TEXT("False"));
double start = FPlatformTime::Seconds();
_numVertecies = 0;
_meshCurrentlyProcessed = 0;
processNode(scene->mRootNode, scene);
double end = FPlatformTime::Seconds();
UE_LOG(LogTemp, Warning, TEXT("Final Number of Vertecies in Scene: %i in %f seconds"), _numVertecies, end - start);
UE_LOG(GLTF, Warning, TEXT("Final Number of Vertecies in Scene: %i in %f seconds"), _numVertecies, end - start);
}
UMaterialInterface *AProceduralEntity::GetMaterialForIndex(unsigned int index, const aiScene* scene){
if (MaterialMap.Contains(index)) {
return *MaterialMap.Find(index);
}
else {
UE_LOG(GLTF, Warning, TEXT("Parsing Material %d"),index);
UMaterialInstanceDynamic* newMaterial = UMaterialInstanceDynamic::Create(MasterMaterialRef, this);
//UMaterialInterface *newMaterial = UMaterial::GetDefaultMaterial(EMaterialDomain::MD_Surface);
aiMaterial* AMat = scene->mMaterials[index];
aiColor3D color(0.f, 0.f, 0.f);
if (AI_SUCCESS == AMat->Get(AI_MATKEY_COLOR_DIFFUSE, color)) {
UE_LOG(GLTF, Warning, TEXT("Material Property: %s, %d %d %d"), TEXT("AI_MATKEY_COLOR_DIFFUSE"), color.r, color.g, color.b);
}
else {
UE_LOG(GLTF, Warning, TEXT("Material Property: %s, Failed"), TEXT("AI_MATKEY_COLOR_DIFFUSE"));
}
if (AMat->GetTextureCount(aiTextureType_DIFFUSE) > 0) {
aiString Path;
if (AMat->GetTexture(aiTextureType_DIFFUSE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) {
FString fileName = FString(Path.C_Str());
FString dirPath, temp , right;
if (!_filePath.Split(TEXT("\\"), &temp, &right, ESearchCase::IgnoreCase, ESearchDir::FromEnd)) {
temp = _filePath;
}
if (!temp.Split(TEXT("/"), &dirPath, &right, ESearchCase::IgnoreCase, ESearchDir::FromEnd)) {
dirPath = temp;
}
UE_LOG(GLTF, Warning, TEXT("Diffuse Texture:\"%s\" \"%s\""), *dirPath, *fileName);
diffTexture = LoadTexture(dirPath, fileName);
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 */
//https://drive.google.com/file/d/0BzqpBc4MrAMXLXN1ZGNzUEJZc1k/edit
//https://forums.unrealengine.com/showthread.php?33446-Creating-UTexture-from-data-in-code-making-it-a-material-and-adding-it-to-a-mesh
UTexture2D* AProceduralEntity::LoadTexture(FString Folder, FString FileName)
{
FString TexturePath = Folder + "\\" + FileName;
UTexture2D* Texture = NULL;
TArray<uint8> FileData;
/* Load DDS texture */
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)
{
NumMips = 1;
}
if (Format == PF_DXT1)
{
BlockSize = 8;
}
/* Create transient texture */
Texture = UTexture2D::CreateTransient(DDSLoadHelper.DDSHeader->dwWidth, DDSLoadHelper.DDSHeader->dwHeight, Format);
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())
{
FTexture2DMipMap& Mip = Texture->PlatformData->Mips[i];
void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);
FMemory::Memcpy(Data, DataPtr, NumBytes);
Mip.BulkData.Unlock();
}
/* Add new mip */
else
{
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;
}
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)
{
IsValid = false;
UTexture2D* LoadedT2D = NULL;
EImageFormat::Type format = EImageFormat::PNG;
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
IImageWrapperPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper(format);
//Load From File
TArray<uint8> RawFileData;
if (!FFileHelper::LoadFileToArray(RawFileData, *FullFilePath)) return NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Create T2D!
if (ImageWrapper.IsValid() && ImageWrapper->SetCompressed(RawFileData.GetData(), RawFileData.Num()))
{
const TArray<uint8>* UncompressedBGRA = NULL;
if (ImageWrapper->GetRaw(ERGBFormat::BGRA, 8, UncompressedBGRA))
{
LoadedT2D = UTexture2D::CreateTransient(ImageWrapper->GetWidth(), ImageWrapper->GetHeight(), PF_B8G8R8A8);
//Valid?
if (!LoadedT2D) return NULL;
//~~~~~~~~~~~~~~
//Out!
Width = ImageWrapper->GetWidth();
Height = ImageWrapper->GetHeight();
//Copy!
void* TextureData = LoadedT2D->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
FMemory::Memcpy(TextureData, UncompressedBGRA->GetData(), UncompressedBGRA->Num());
LoadedT2D->PlatformData->Mips[0].BulkData.Unlock();
//Update!
LoadedT2D->UpdateResource();
}
}
// Success!
IsValid = true;
return LoadedT2D;
}
\ No newline at end of file
......@@ -23,6 +23,9 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Generation")
FString _filePath;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Materials")
UMaterialInterface * MasterMaterialRef;
// Sets default values for this actor's properties
AProceduralEntity();
......@@ -37,6 +40,12 @@ public:
UFUNCTION(BlueprintCallable, Category = ProceduralEntity)
void loadModelFromBlueprint();
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Materials")
TMap<int32, UMaterialInterface *> MaterialMap;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Materials")
UTexture2D* diffTexture;
private:
int32 _selectedVertex;
int32 _meshCurrentlyProcessed;
......@@ -52,6 +61,8 @@ private:
TArray<TArray<FProcMeshTangent>> _tangents;
TArray<TArray<FColor>> _vertexColors;
//USceneComponent* _rootComp;
/* ################################################### */
......@@ -67,4 +78,8 @@ private:
void processMesh(aiMesh* mesh, const aiScene* scene);
void processNode(aiNode* node, const aiScene* scene);
void loadModel(std::string path);
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);
};
\ 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