Browse Source

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

OTHGMars 6 years ago
parent
commit
0859b29fa1

+ 59 - 2
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)

+ 2 - 0
Engine/source/ts/assimp/assimpShapeLoader.h

@@ -26,6 +26,7 @@
 #ifndef _TSSHAPELOADER_H_
 #include "ts/loader/tsShapeLoader.h"
 #endif
+#include <assimp/texture.h>
 
 //-----------------------------------------------------------------------------
 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();