Browse Source

Add the ability to import textures from the GLTF importer

Panagiotis Christopoulos Charitos 3 years ago
parent
commit
00c0dbd6f0

+ 2 - 0
AnKi/Importer/GltfImporter.cpp

@@ -214,6 +214,8 @@ Error GltfImporter::init(const GltfImporterInitInfo& initInfo)
 		m_hive = newInstance<ThreadHive>(*m_pool, threadCount, m_pool, true);
 	}
 
+	m_importTextures = initInfo.m_importTextures;
+
 	return Error::kNone;
 }
 

+ 3 - 0
AnKi/Importer/GltfImporter.h

@@ -34,6 +34,7 @@ public:
 	F32 m_lightIntensityScale = 1.0f;
 	U32 m_threadCount = kMaxU32;
 	CString m_comment;
+	Bool m_importTextures = false;
 };
 
 /// Import GLTF and spit AnKi scenes.
@@ -88,6 +89,8 @@ private:
 	/// Don't generate LODs for meshes with less vertices than this number.
 	U32 m_skipLodVertexCountThreshold = 256;
 
+	Bool m_importTextures = false;
+
 	// Misc
 	Error getExtras(const cgltf_extras& extras, HashMapRaii<CString, StringRaii>& out);
 	Error parseArrayOfNumbers(CString str, DynamicArrayRaii<F64>& out, const U32* expectedArraySize = nullptr);

+ 90 - 4
AnKi/Importer/GltfImporterMaterial.cpp

@@ -4,9 +4,11 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Importer/GltfImporter.h>
+#include <AnKi/Importer/ImageImporter.h>
 #include <AnKi/Resource/ImageLoader.h>
 #include <AnKi/Util/WeakArray.h>
 #include <AnKi/Util/Xml.h>
+#include <AnKi/Util/Filesystem.h>
 
 namespace anki {
 
@@ -98,6 +100,53 @@ static Error findConstantColorsInImage(CString fname, Vec4& constantColor, BaseM
 	return Error::kNone;
 }
 
+static Error importImage(BaseMemoryPool& pool, CString in, CString out, Bool alpha)
+{
+	ImageImporterConfig config;
+
+	config.m_pool = &pool;
+
+	Array<CString, 1> inputFnames = {in};
+	config.m_inputFilenames = inputFnames;
+
+	config.m_outFilename = out;
+	config.m_compressions = ImageBinaryDataCompression::kS3tc | ImageBinaryDataCompression::kAstc;
+	config.m_minMipmapDimension = 8;
+	config.m_noAlpha = !alpha;
+
+	StringRaii tmp(&pool);
+	if(getTempDirectory(tmp))
+	{
+		ANKI_IMPORTER_LOGE("getTempDirectory() failed");
+		return 1;
+	}
+	config.m_tempDirectory = tmp;
+
+#if ANKI_OS_WINDOWS
+	config.m_compressonatorFilename =
+		ANKI_SOURCE_DIRECTORY "/ThirdParty/Bin/Windows64/Compressonator/compressonatorcli.exe";
+	config.m_astcencFilename = ANKI_SOURCE_DIRECTORY "/ThirdParty/Bin/Windows64/astcenc-avx2.exe";
+#elif ANKI_OS_LINUX
+	config.m_compressonatorFilename = ANKI_SOURCE_DIRECTORY "/ThirdParty/Bin/Linux64/Compressonator/compressonatorcli";
+	config.m_astcencFilename = ANKI_SOURCE_DIRECTORY "/ThirdParty/Bin/Linux64/astcenc-avx2";
+#else
+#	error "Unupported"
+#endif
+
+	ANKI_IMPORTER_LOGV("Importing image \"%s\" as \"%s\"", in.cstr(), out.cstr());
+	ANKI_CHECK(importImage(config));
+
+	return Error::kNone;
+}
+
+static void fixImageUri(StringRaii& uri)
+{
+	uri.replaceAll(".tga", ".ankitex");
+	uri.replaceAll(".png", ".ankitex");
+	uri.replaceAll(".jpg", ".ankitex");
+	uri.replaceAll(".jpeg", ".ankitex");
+}
+
 Error GltfImporter::writeMaterial(const cgltf_material& mtl, Bool writeRayTracing)
 {
 	StringRaii fname(m_pool);
@@ -139,6 +188,14 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, Bool writeRayTracin
 
 		const Bool constantAlpha = constantColor.w() >= 0.0f;
 		xml.replaceAll("%alphaTestMutator%", (constantAlpha) ? "0" : "1");
+
+		if(m_importTextures)
+		{
+			StringRaii out = m_outDir;
+			out.append(fname);
+			fixImageUri(out);
+			ANKI_CHECK(importImage(*m_pool, fname, out, !constantAlpha));
+		}
 	}
 	else
 	{
@@ -196,6 +253,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, Bool writeRayTracin
 	}
 
 	// Roughness
+	Bool bRoughnessMetalicTexture = false;
 	if(mtl.pbr_metallic_roughness.metallic_roughness_texture.texture && constantRoughness < 0.0f)
 	{
 		StringRaii uri(m_pool);
@@ -206,6 +264,8 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, Bool writeRayTracin
 					   StringRaii(m_pool).sprintf("<input name=\"m_roughnessTex\" value=\"%s\"/>", uri.cstr()));
 
 		xml.replaceAll("%roughnessTexMutator%", "1");
+
+		bRoughnessMetalicTexture = true;
 	}
 	else
 	{
@@ -230,6 +290,8 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, Bool writeRayTracin
 					   StringRaii(m_pool).sprintf("<input name=\"m_metallicTex\" value=\"%s\"/>", uri.cstr()));
 
 		xml.replaceAll("%metalTexMutator%", "1");
+
+		bRoughnessMetalicTexture = true;
 	}
 	else
 	{
@@ -243,6 +305,15 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, Bool writeRayTracin
 		xml.replaceAll("%metalTexMutator%", "0");
 	}
 
+	if(bRoughnessMetalicTexture && m_importTextures)
+	{
+		CString in = getTextureUri(mtl.pbr_metallic_roughness.metallic_roughness_texture);
+		StringRaii out = m_outDir;
+		out.append(in);
+		fixImageUri(out);
+		ANKI_CHECK(importImage(*m_pool, in, out, false));
+	}
+
 	// Normal texture
 	if(mtl.normal_texture.texture)
 	{
@@ -257,6 +328,15 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, Bool writeRayTracin
 						   StringRaii(m_pool).sprintf("<input name=\"m_normalTex\" value=\"%s\"/>", uri.cstr()));
 
 			xml.replaceAll("%normalTexMutator%", "1");
+
+			if(m_importTextures)
+			{
+				CString in = getTextureUri(mtl.normal_texture);
+				StringRaii out = m_outDir;
+				out.append(in);
+				fixImageUri(out);
+				ANKI_CHECK(importImage(*m_pool, in, out, false));
+			}
 		}
 		else
 		{
@@ -280,6 +360,15 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, Bool writeRayTracin
 					   StringRaii(m_pool).sprintf("<input name=\"m_emissiveTex\" value=\"%s\"/>", uri.cstr()));
 
 		xml.replaceAll("%emissiveTexMutator%", "1");
+
+		if(m_importTextures)
+		{
+			CString in = getTextureUri(mtl.emissive_texture);
+			StringRaii out = m_outDir;
+			out.append(in);
+			fixImageUri(out);
+			ANKI_CHECK(importImage(*m_pool, in, out, false));
+		}
 	}
 	else
 	{
@@ -329,10 +418,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, Bool writeRayTracin
 	}
 
 	// Replace texture extensions with .anki
-	xml.replaceAll(".tga", ".ankitex");
-	xml.replaceAll(".png", ".ankitex");
-	xml.replaceAll(".jpg", ".ankitex");
-	xml.replaceAll(".jpeg", ".ankitex");
+	fixImageUri(xml);
 
 	// Write file
 	File file;

+ 13 - 8
AnKi/Importer/ImageImporter.cpp

@@ -13,6 +13,8 @@
 
 namespace anki {
 
+static Atomic<U32> g_tempFileIndex = {1}; // Used to create random names
+
 namespace {
 
 class SurfaceOrVolumeData
@@ -322,7 +324,8 @@ static Error resizeImage(CString inImageFilename, U32 outWidth, U32 outHeight, C
 	}
 
 	// Store
-	tmpFilename.sprintf("%s/AnKiImageImporter_%u.%s", tempDirectory.cstr(), U32(std::rand()), (hdr) ? "exr" : "png");
+	tmpFilename.sprintf("%s/AnKiImageImporter_%u.%s", tempDirectory.cstr(), g_tempFileIndex.fetchAdd(1),
+						(hdr) ? "exr" : "png");
 	ANKI_IMPORTER_LOGV("Will store: %s", tmpFilename.cstr());
 
 	if(!hdr)
@@ -615,7 +618,8 @@ static Error compressS3tc(BaseMemoryPool& pool, CString tempDirectory, CString c
 
 	// Create a PNG image to feed to the compressor
 	StringRaii tmpFilename(&pool);
-	tmpFilename.sprintf("%s/AnKiImageImporter_%u.%s", tempDirectory.cstr(), U32(std::rand()), (hdr) ? "exr" : "png");
+	tmpFilename.sprintf("%s/AnKiImageImporter_%u.%s", tempDirectory.cstr(), g_tempFileIndex.fetchAdd(1),
+						(hdr) ? "exr" : "png");
 	ANKI_IMPORTER_LOGV("Will store: %s", tmpFilename.cstr());
 	Bool saveTmpImageOk = false;
 	if(!hdr)
@@ -639,7 +643,7 @@ static Error compressS3tc(BaseMemoryPool& pool, CString tempDirectory, CString c
 
 	// Invoke the compressor process
 	StringRaii ddsFilename(&pool);
-	ddsFilename.sprintf("%s/AnKiImageImporter_%u.dds", tempDirectory.cstr(), U32(std::rand()));
+	ddsFilename.sprintf("%s/AnKiImageImporter_%u.dds", tempDirectory.cstr(), g_tempFileIndex.fetchAdd(1));
 	Process proc;
 	Array<CString, 5> args;
 	U32 argCount = 0;
@@ -649,8 +653,8 @@ static Error compressS3tc(BaseMemoryPool& pool, CString tempDirectory, CString c
 	args[argCount++] = tmpFilename;
 	args[argCount++] = ddsFilename;
 
-	ANKI_IMPORTER_LOGV("Will invoke process: compressonatorcli %s %s %s %s %s", args[0].cstr(), args[1].cstr(),
-					   args[2].cstr(), args[3].cstr(), args[4].cstr());
+	ANKI_IMPORTER_LOGV("Will invoke process: %s %s %s %s %s %s", compressonatorFilename.cstr(), args[0].cstr(),
+					   args[1].cstr(), args[2].cstr(), args[3].cstr(), args[4].cstr());
 	ANKI_CHECK(proc.start(compressonatorFilename, args));
 	CleanupFile ddsCleanup(&pool, ddsFilename);
 	ProcessStatus status;
@@ -727,7 +731,8 @@ static Error compressAstc(BaseMemoryPool& pool, CString tempDirectory, CString a
 
 	// Create a BMP image to feed to the astcebc
 	StringRaii tmpFilename(&pool);
-	tmpFilename.sprintf("%s/AnKiImageImporter_%u.%s", tempDirectory.cstr(), U32(std::rand()), (hdr) ? "exr" : "png");
+	tmpFilename.sprintf("%s/AnKiImageImporter_%u.%s", tempDirectory.cstr(), g_tempFileIndex.fetchAdd(1),
+						(hdr) ? "exr" : "png");
 	ANKI_IMPORTER_LOGV("Will store: %s", tmpFilename.cstr());
 	Bool saveTmpImageOk = false;
 	if(!hdr)
@@ -751,7 +756,7 @@ static Error compressAstc(BaseMemoryPool& pool, CString tempDirectory, CString a
 
 	// Invoke the compressor process
 	StringRaii astcFilename(&pool);
-	astcFilename.sprintf("%s/AnKiImageImporter_%u.astc", tempDirectory.cstr(), U32(std::rand()));
+	astcFilename.sprintf("%s/AnKiImageImporter_%u.astc", tempDirectory.cstr(), g_tempFileIndex.fetchAdd(1));
 	StringRaii blockStr(&pool);
 	blockStr.sprintf("%ux%u", blockSize.x(), blockSize.y());
 	Process proc;
@@ -763,7 +768,7 @@ static Error compressAstc(BaseMemoryPool& pool, CString tempDirectory, CString a
 	args[argCount++] = blockStr;
 	args[argCount++] = "-fast";
 
-	ANKI_IMPORTER_LOGV("Will invoke process: astcenc-avx2 %s %s %s %s %s", args[0].cstr(), args[1].cstr(),
+	ANKI_IMPORTER_LOGV("Will invoke process: %s %s %s %s %s %s", astcencFilename.cstr(), args[0].cstr(), args[1].cstr(),
 					   args[2].cstr(), args[3].cstr(), args[4].cstr());
 	ANKI_CHECK(proc.start(astcencFilename, args));
 

+ 8 - 3
AnKi/Util/String.h

@@ -429,6 +429,11 @@ public:
 	void create(TMemPool& pool, ConstIterator first, ConstIterator last)
 	{
 		ANKI_ASSERT(first != 0 && last != 0);
+		for(ConstIterator it = first; it < last; ++it)
+		{
+			ANKI_ASSERT(*it != '\0');
+		}
+
 		auto length = last - first;
 		m_data.create(pool, length + 1);
 
@@ -841,7 +846,7 @@ public:
 	{
 		if(!b.isEmpty())
 		{
-			create(b.m_data.getBegin(), b.m_data.getEnd());
+			create(b.m_data.getBegin(), b.m_data.getEnd() - 1);
 		}
 	}
 
@@ -873,7 +878,7 @@ public:
 		m_pool = b.m_pool;
 		if(!b.isEmpty())
 		{
-			create(b.m_data.getBegin(), b.m_data.getEnd());
+			create(b.m_data.getBegin(), b.m_data.getEnd() - 1);
 		}
 		return *this;
 	}
@@ -884,7 +889,7 @@ public:
 		destroy();
 		if(!b.isEmpty())
 		{
-			create(b.getBegin(), b.getEnd());
+			create(b.getBegin(), b.getEnd() - 1);
 		}
 		return *this;
 	}

BIN
ThirdParty/Bin/Windows64/Compressonator/Qt5Widgets.dll


+ 20 - 2
Tools/GltfImporter/Main.cpp

@@ -14,9 +14,10 @@ Options:
 -optimize-meshes <0|1>     : Optimize meshes. Default is 1
 -optimize-animations <0|1> : Optimize animations. Default is 1
 -j <thread_count>          : Number of threads. Defaults to system's max
--lod-count <1|2|3>         : The number of geometry LODs to generate. Default: 1
+-lod-count <1|2|3>         : The number of geometry LODs to generate. Default is 1
 -lod-factor <float>        : The decimate factor for each LOD. Default 0.25
--light-scale <float>       : Multiply the light intensity with this number. Default 1.0
+-light-scale <float>       : Multiply the light intensity with this number. Default is 1.0
+-import-testures <0|1>     : Import textures. Default is 0
 -v                         : Enable verbose log
 )";
 
@@ -30,6 +31,7 @@ public:
 	StringRaii m_texRpath = {&m_pool};
 	Bool m_optimizeMeshes = true;
 	Bool m_optimizeAnimations = true;
+	Bool m_importTextures = false;
 	U32 m_threadCount = kMaxU32;
 	U32 m_lodCount = 1;
 	F32 m_lodFactor = 0.25f;
@@ -182,6 +184,21 @@ static Error parseCommandLineArgs(int argc, char** argv, CmdLineArgs& info)
 				return Error::kUserData;
 			}
 		}
+		else if(strcmp(argv[i], "-import-textures") == 0)
+		{
+			++i;
+
+			if(i < argc)
+			{
+				I val = 1;
+				ANKI_CHECK(CString(argv[i]).toNumber(val));
+				info.m_importTextures = val != 0;
+			}
+			else
+			{
+				return Error::kUserData;
+			}
+		}
 		else
 		{
 			return Error::kUserData;
@@ -242,6 +259,7 @@ int myMain(int argc, char** argv)
 	initInfo.m_lightIntensityScale = cmdArgs.m_lightIntensityScale;
 	initInfo.m_threadCount = cmdArgs.m_threadCount;
 	initInfo.m_comment = comment;
+	initInfo.m_importTextures = cmdArgs.m_importTextures;
 
 	GltfImporter importer(&pool);
 	if(importer.init(initInfo))