From 0859b29fa1a392cbfde58206c37f9de953927aed Mon Sep 17 00:00:00 2001 From: OTHGMars Date: Sun, 21 Apr 2019 23:59:40 -0400 Subject: [PATCH] Embedded texture extraction. Caches textures to disk for shape formats that support embedded textures. Only the compressed texture codepath has been tested. There are a large number of binary gltf files with embedded (and pbr) textures for testing here: https://github.com/KhronosGroup/glTF-Sample-Models --- Engine/source/ts/assimp/assimpShapeLoader.cpp | 61 ++++++++++++++++++- Engine/source/ts/assimp/assimpShapeLoader.h | 2 + 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/Engine/source/ts/assimp/assimpShapeLoader.cpp b/Engine/source/ts/assimp/assimpShapeLoader.cpp index f0e543704..46596a92b 100644 --- a/Engine/source/ts/assimp/assimpShapeLoader.cpp +++ b/Engine/source/ts/assimp/assimpShapeLoader.cpp @@ -200,6 +200,10 @@ void AssimpShapeLoader::enumerateScene() Con::printf("[ASSIMP] Mesh Count: %d", mScene->mNumMeshes); Con::printf("[ASSIMP] Material Count: %d", mScene->mNumMaterials); + // Extract embedded textures + for (U32 i = 0; i < mScene->mNumTextures; ++i) + extractTexture(i, mScene->mTextures[i]); + // Load all the materials. for ( U32 i = 0; i < mScene->mNumMaterials; i++ ) AppMesh::appMaterials.push_back(new AssimpAppMaterial(mScene->mMaterials[i])); @@ -302,8 +306,11 @@ void AssimpShapeLoader::updateMaterialsScript(const Torque::Path &path) if ( Sim::findObject( MATMGR->getMapEntry( mat->getName() ), mappedMat ) ) { // Only update existing materials if forced to - if ( ColladaUtils::getOptions().forceUpdateMaterials ) - persistMgr.setDirty( mappedMat ); + if (Con::getBoolVariable("$Assimp::ForceUpdateMats", false)) + { + mat->initMaterial(scriptPath, mappedMat); + persistMgr.setDirty(mappedMat); + } } else { @@ -393,6 +400,56 @@ void AssimpShapeLoader::detectDetails() AssimpAppMesh::fixDetailSize(singleDetail, Con::getIntVariable("$Assimp::singleDetailSize", 2)); } +void AssimpShapeLoader::extractTexture(U32 index, aiTexture* pTex) +{ // Cache an embedded texture to disk + updateProgress(Load_EnumerateScene, "Extracting Textures...", mScene->mNumTextures, index); + Con::printf("[Assimp] Extracting Texture %s, W: %d, H: %d, %d of %d, format hint: (%s)", pTex->mFilename.C_Str(), + pTex->mWidth, pTex->mHeight, index, mScene->mNumTextures, pTex->achFormatHint); + + // Create the texture filename + String cleanFile = AppMaterial::cleanString(TSShapeLoader::getShapePath().getFileName()); + String texName = String::ToString("%s_cachedTex%d", cleanFile.c_str(), index); + Torque::Path texPath = shapePath; + texPath.setFileName(texName); + + if (pTex->mHeight == 0) + { // Compressed format, write the data directly to disc + texPath.setExtension(pTex->achFormatHint); + FileStream *outputStream; + if ((outputStream = FileStream::createAndOpen(texPath.getFullPath(), Torque::FS::File::Write)) != NULL) + { + outputStream->setPosition(0); + outputStream->write(pTex->mWidth, pTex->pcData); + outputStream->close(); + delete outputStream; + } + } + else + { // Embedded pixel data, fill a bitmap and save it. + GFXTexHandle shapeTex; + shapeTex.set(pTex->mWidth, pTex->mHeight, GFXFormatR8G8B8A8_SRGB, &GFXDynamicTextureSRGBProfile, + String::ToString("AssimpShapeLoader (%s:%i)", __FILE__, __LINE__), 1, 0); + GFXLockedRect *rect = shapeTex.lock(); + + for (U32 y = 0; y < pTex->mHeight; ++y) + { + for (U32 x = 0; x < pTex->mWidth; ++x) + { + U32 targetIndex = (y * rect->pitch) + (x * 4); + U32 sourceIndex = ((y * pTex->mWidth) + x) * 4; + rect->bits[targetIndex] = pTex->pcData[sourceIndex].r; + rect->bits[targetIndex + 1] = pTex->pcData[sourceIndex].g; + rect->bits[targetIndex + 2] = pTex->pcData[sourceIndex].b; + rect->bits[targetIndex + 3] = pTex->pcData[sourceIndex].a; + } + } + shapeTex.unlock(); + + texPath.setExtension("png"); + shapeTex->dumpToDisk("PNG", texPath.getFullPath()); + } +} + //----------------------------------------------------------------------------- /// This function is invoked by the resource manager based on file extension. TSShape* assimpLoadShape(const Torque::Path &path) diff --git a/Engine/source/ts/assimp/assimpShapeLoader.h b/Engine/source/ts/assimp/assimpShapeLoader.h index 713e403cc..848baaaf9 100644 --- a/Engine/source/ts/assimp/assimpShapeLoader.h +++ b/Engine/source/ts/assimp/assimpShapeLoader.h @@ -26,6 +26,7 @@ #ifndef _TSSHAPELOADER_H_ #include "ts/loader/tsShapeLoader.h" #endif +#include //----------------------------------------------------------------------------- class AssimpShapeLoader : public TSShapeLoader @@ -37,6 +38,7 @@ protected: virtual bool ignoreNode(const String& name); void detectDetails(); + void extractTexture(U32 index, aiTexture* pTex); public: AssimpShapeLoader();