Prechádzať zdrojové kódy

Add submesh support in the GLTF exporter

Panagiotis Christopoulos Charitos 4 rokov pred
rodič
commit
94bd70e08b

+ 49 - 43
AnKi/Importer/GltfImporter.cpp

@@ -597,15 +597,19 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 			struct Ctx
 			{
 				GltfImporter* m_importer;
-				cgltf_mesh* m_mesh;
-				cgltf_material* m_mtl;
-				cgltf_skin* m_skin;
+				const cgltf_mesh* m_mesh;
+				Array<const cgltf_material*, 128> m_materials;
+				U32 m_materialCount = 0;
+				const cgltf_skin* m_skin;
 				RayTypeBit m_rayTypes;
 			};
 			Ctx* ctx = m_alloc.newInstance<Ctx>();
 			ctx->m_importer = this;
 			ctx->m_mesh = node.mesh;
-			ctx->m_mtl = node.mesh->primitives[0].material;
+			for(U32 i = 0; i < node.mesh->primitives_count; ++i)
+			{
+				ctx->m_materials[ctx->m_materialCount++] = node.mesh->primitives[i].material;
+			}
 			ctx->m_skin = node.skin;
 			ctx->m_rayTypes = (skipRt) ? RayTypeBit::NONE : RayTypeBit::ALL;
 
@@ -645,9 +649,9 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 					err = self.m_importer->writeMesh(*self.m_mesh, name, self.m_importer->computeLodFactor(2));
 				}
 
-				if(!err)
+				for(U32 i = 0; i < self.m_materialCount && !err; ++i)
 				{
-					err = self.m_importer->writeMaterial(*self.m_mtl, self.m_rayTypes);
+					err = self.m_importer->writeMaterial(*self.m_materials[i], self.m_rayTypes);
 				}
 
 				if(!err)
@@ -749,16 +753,9 @@ Error GltfImporter::writeTransform(const Transform& trf)
 
 Error GltfImporter::writeModel(const cgltf_mesh& mesh)
 {
-	StringAuto modelFname(m_alloc);
-	modelFname.sprintf("%s%s_%s.ankimdl", m_outDir.cstr(), mesh.name, mesh.primitives[0].material->name);
+	const StringAuto modelFname = computeModelResourceFilename(mesh);
 	ANKI_GLTF_LOGI("Importing model %s", modelFname.cstr());
 
-	if(mesh.primitives_count != 1)
-	{
-		ANKI_GLTF_LOGE("For now only one primitive is supported");
-		return Error::USER_DATA;
-	}
-
 	HashMapAuto<CString, StringAuto> extras(m_alloc);
 	ANKI_CHECK(getExtras(mesh.extras, extras));
 
@@ -768,38 +765,48 @@ Error GltfImporter::writeModel(const cgltf_mesh& mesh)
 	ANKI_CHECK(file.writeText("<model>\n"));
 	ANKI_CHECK(file.writeText("\t<modelPatches>\n"));
 
-	ANKI_CHECK(file.writeText("\t\t<modelPatch>\n"));
+	for(U32 primIdx = 0; primIdx < mesh.primitives_count; ++primIdx)
+	{
+		if(mesh.primitives_count == 1)
+		{
+			ANKI_CHECK(file.writeText("\t\t<modelPatch>\n"));
+		}
+		else
+		{
+			ANKI_CHECK(file.writeText("\t\t<modelPatch subMeshIndex=\"%u\">\n", primIdx));
+		}
 
-	ANKI_CHECK(file.writeText("\t\t\t<mesh>%s%s.ankimesh</mesh>\n", m_rpath.cstr(), mesh.name));
+		ANKI_CHECK(file.writeText("\t\t\t<mesh>%s%s.ankimesh</mesh>\n", m_rpath.cstr(), mesh.name));
 
-	if(m_lodCount > 1 && !skipMeshLod(mesh, 1))
-	{
-		StringAuto name(m_alloc);
-		name.sprintf("%s_lod1", mesh.name);
-		ANKI_CHECK(file.writeText("\t\t\t<mesh1>%s%s.ankimesh</mesh1>\n", m_rpath.cstr(), name.cstr()));
-	}
+		if(m_lodCount > 1 && !skipMeshLod(mesh, 1))
+		{
+			StringAuto name(m_alloc);
+			name.sprintf("%s_lod1", mesh.name);
+			ANKI_CHECK(file.writeText("\t\t\t<mesh1>%s%s.ankimesh</mesh1>\n", m_rpath.cstr(), name.cstr()));
+		}
 
-	if(m_lodCount > 2 && !skipMeshLod(mesh, 2))
-	{
-		StringAuto name(m_alloc);
-		name.sprintf("%s_lod2", mesh.name);
-		ANKI_CHECK(file.writeText("\t\t\t<mesh2>%s%s.ankimesh</mesh2>\n", m_rpath.cstr(), name.cstr()));
-	}
+		if(m_lodCount > 2 && !skipMeshLod(mesh, 2))
+		{
+			StringAuto name(m_alloc);
+			name.sprintf("%s_lod2", mesh.name);
+			ANKI_CHECK(file.writeText("\t\t\t<mesh2>%s%s.ankimesh</mesh2>\n", m_rpath.cstr(), name.cstr()));
+		}
 
-	HashMapAuto<CString, StringAuto> materialExtras(m_alloc);
-	ANKI_CHECK(getExtras(mesh.primitives[0].material->extras, materialExtras));
-	auto mtlOverride = materialExtras.find("material_override");
-	if(mtlOverride != materialExtras.getEnd())
-	{
-		ANKI_CHECK(file.writeText("\t\t\t<material>%s</material>\n", mtlOverride->cstr()));
-	}
-	else
-	{
-		ANKI_CHECK(file.writeText("\t\t\t<material>%s%s.ankimtl</material>\n", m_rpath.cstr(),
-								  mesh.primitives[0].material->name));
-	}
+		HashMapAuto<CString, StringAuto> materialExtras(m_alloc);
+		ANKI_CHECK(getExtras(mesh.primitives[primIdx].material->extras, materialExtras));
+		auto mtlOverride = materialExtras.find("material_override");
+		if(mtlOverride != materialExtras.getEnd())
+		{
+			ANKI_CHECK(file.writeText("\t\t\t<material>%s</material>\n", mtlOverride->cstr()));
+		}
+		else
+		{
+			ANKI_CHECK(file.writeText("\t\t\t<material>%s%s.ankimtl</material>\n", m_rpath.cstr(),
+									  mesh.primitives[primIdx].material->name));
+		}
 
-	ANKI_CHECK(file.writeText("\t\t</modelPatch>\n"));
+		ANKI_CHECK(file.writeText("\t\t</modelPatch>\n"));
+	}
 
 	ANKI_CHECK(file.writeText("\t</modelPatches>\n"));
 
@@ -1333,8 +1340,7 @@ Error GltfImporter::writeModelNode(const cgltf_node& node, const HashMapAuto<CSt
 	HashMapAuto<CString, StringAuto> extras(parentExtras);
 	ANKI_CHECK(getExtras(node.extras, extras));
 
-	StringAuto modelFname(m_alloc);
-	modelFname.sprintf("%s%s_%s.ankimdl", m_rpath.cstr(), node.mesh->name, node.mesh->primitives[0].material->name);
+	const StringAuto modelFname = computeModelResourceFilename(*node.mesh);
 
 	ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newModelNode(\"%s\")\n", getNodeName(node).cstr()));
 	ANKI_CHECK(m_sceneFile.writeText("node:getSceneNodeBase():getModelComponent():loadModelResource(\"%s\")\n",

+ 20 - 0
AnKi/Importer/GltfImporter.h

@@ -6,6 +6,7 @@
 #pragma once
 
 #include <AnKi/Util/String.h>
+#include <AnKi/Util/StringList.h>
 #include <AnKi/Util/File.h>
 #include <AnKi/Util/HashMap.h>
 #include <AnKi/Resource/Common.h>
@@ -129,6 +130,25 @@ private:
 
 	static U32 getMeshTotalVertexCount(const cgltf_mesh& mesh);
 
+	StringAuto computeModelResourceFilename(const cgltf_mesh& mesh) const
+	{
+		StringListAuto list(m_alloc);
+
+		list.pushBackSprintf("%s%s", m_rpath.cstr(), mesh.name);
+
+		for(U i = 0; i < mesh.primitives_count; ++i)
+		{
+			list.pushBackSprintf("_%s", mesh.primitives[i].material->name);
+		}
+
+		list.pushBack(".ankimdl");
+
+		StringAuto out(m_alloc);
+		list.join("", out);
+
+		return out;
+	}
+
 	// Resources
 	ANKI_USE_RESULT Error writeMesh(const cgltf_mesh& mesh, CString nameOverride, F32 decimateFactor);
 	ANKI_USE_RESULT Error writeMaterial(const cgltf_material& mtl, RayTypeBit usedRayTypes);

+ 1 - 1
AnKi/Resource/MeshBinaryLoader.cpp

@@ -38,7 +38,7 @@ Error MeshBinaryLoader::load(const ResourceFilename& filename)
 		U idxSum = 0;
 		for(U i = 0; i < m_subMeshes.getSize(); i++)
 		{
-			const MeshBinarySubMesh& sm = m_subMeshes[0];
+			const MeshBinarySubMesh& sm = m_subMeshes[i];
 			if(sm.m_firstIndex != idxSum || (sm.m_indexCount % indicesPerFace) != 0)
 			{
 				ANKI_RESOURCE_LOGE("Incorrect sub mesh info");

+ 1 - 1
AnKi/Util/Filesystem.cpp

@@ -32,7 +32,7 @@ void getFilepathFilename(const CString& filename, StringAuto& out)
 
 	if(pc == nullptr)
 	{
-		// Do nothing
+		out.create(filename);
 	}
 	else
 	{

+ 1 - 1
Samples/SimpleScene/Assets/Scene.lua

@@ -1,4 +1,4 @@
--- Generated by: ../../../buildd/Bin/GltfImporter CornellBox.gltf /home/godlike/src/anki/Samples/SimpleScene/Assets -rpath Assets -texrpath Assets -lod-count 1
+-- Generated by: ../../../buildr/Bin/GltfImporter CornellBox.gltf /home/godlike/src/anki/Samples/SimpleScene/Assets -rpath Assets -texrpath Assets -lod-count 1
 local scene = getSceneGraph()
 local events = getEventManager()