Browse Source

Some more work on the gltf exporter

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
dc975866ae
3 changed files with 199 additions and 5 deletions
  1. 180 4
      tools/gltf_exporter/Exporter.cpp
  2. 2 1
      tools/gltf_exporter/Exporter.h
  3. 17 0
      tools/gltf_exporter/TinyGltf.cpp

+ 180 - 4
tools/gltf_exporter/Exporter.cpp

@@ -6,6 +6,7 @@
 #include "Exporter.h"
 #include <anki/resource/MeshLoader.h>
 #include <anki/util/File.h>
+#include <string>
 
 namespace anki
 {
@@ -17,6 +18,24 @@ public:
 	U8 m_weights[4] = {0, 0, 0, 0};
 };
 
+static std::string replaceAllString(const std::string& str, const std::string& from, const std::string& to)
+{
+	if(from.empty())
+	{
+		return str;
+	}
+
+	std::string out = str;
+	size_t start_pos = 0;
+	while((start_pos = out.find(from, start_pos)) != std::string::npos)
+	{
+		out.replace(start_pos, from.length(), to);
+		start_pos += to.length();
+	}
+
+	return out;
+}
+
 Error Exporter::load()
 {
 	std::string err, warn;
@@ -658,22 +677,179 @@ Error Exporter::exportMesh(const tinygltf::Mesh& mesh)
 	return Error::NONE;
 }
 
-void Exporter::getTexture(tinygltf::Material& mtl, CString texName, CString& fname) const
+Bool Exporter::getTexture(const tinygltf::Material& mtl, CString texName, StringAuto& fname) const
 {
+	fname.destroy();
+
 	if(mtl.values.find(texName.cstr()) != mtl.values.end())
 	{
-		const I textureIdx = mtl.values["baseColorTexture"].TextureIndex();
+		const I textureIdx = mtl.values.find(texName.cstr())->second.TextureIndex();
+		ANKI_ASSERT(textureIdx > -1);
 		const I imageIdx = m_model.textures[textureIdx].source;
-		fname = m_model.images[imageIdx].uri.c_str();
+		fname.sprintf("%s/%s", m_texrpath.cstr(), m_model.images[imageIdx].uri.c_str());
+
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+Bool Exporter::getMaterialAttrib(const tinygltf::Material& mtl, CString attribName, Vec4& value) const
+{
+	auto it = mtl.values.find(attribName.cstr());
+	if(it != mtl.values.end())
+	{
+		const tinygltf::Parameter& param = it->second;
+		if(param.has_number_value)
+		{
+			value = Vec4(param.number_value);
+		}
+		else
+		{
+			value =
+				Vec4(param.ColorFactor()[0], param.ColorFactor()[1], param.ColorFactor()[2], param.ColorFactor()[3]);
+		}
+
+		return true;
 	}
 	else
 	{
-		fname = CString();
+		return false;
 	}
 }
 
 Error Exporter::exportMaterial(const tinygltf::Material& mtl)
 {
+	const char* MATERIAL_TEMPLATE = R"(<?xml version="1.0" encoding="UTF-8" ?>
+<!-- This file is auto generated -->
+<material shaderProgram="shaders/GBufferGeneric.glslp">
+	<mutators>
+		<mutator name="DIFFUSE_TEX" value="%diffTexMutator%"/>
+		<mutator name="SPECULAR_TEX" value="%specTexMutator%"/>
+		<mutator name="ROUGHNESS_TEX" value="%roughnessTexMutator%"/>
+		<mutator name="METAL_TEX" value="%metalTexMutator%"/>
+		<mutator name="NORMAL_TEX" value="%normalTexMutator%"/>
+		<mutator name="PARALLAX" value="%parallaxMutator%"/>
+		<mutator name="EMISSIVE_TEX" value="%emissiveTexMutator%"/>
+	</mutators>
+	<inputs>
+		<input shaderInput="mvp" builtin="MODEL_VIEW_PROJECTION_MATRIX"/>
+		<input shaderInput="prevMvp" builtin="PREVIOUS_MODEL_VIEW_PROJECTION_MATRIX"/>
+		<input shaderInput="rotationMat" builtin="ROTATION_MATRIX"/>
+		%parallaxInput%
+
+		%diff%
+		%spec%
+		%roughness%
+		%metallic%
+		%normal%
+		%emission%
+		%subsurface%
+		%height%
+	</inputs>
+</material>
+)";
+
+	std::string xml = MATERIAL_TEMPLATE;
+
+	// Diffuse
+	StringAuto fname(m_alloc);
+	Vec4 v4;
+	if(getTexture(mtl, "baseColorTexture", fname))
+	{
+		xml = replaceAllString(xml, "%diffTexMutator%", "1");
+		xml = replaceAllString(
+			xml, "%diff%", "<input shaderInput=\"diffTex\" value=\"" + std::string(fname.cstr()) + "\"/>");
+	}
+	else if(getMaterialAttrib(mtl, "baseColorFactor", v4))
+	{
+		xml = replaceAllString(xml, "%diffTexMutator%", "0");
+		xml = replaceAllString(xml,
+			"%diff%",
+			"<input shaderInput=\"diffColor\" value=\"" + std::to_string(v4[0]) + " " + std::to_string(v4[1]) + " "
+				+ std::to_string(v4[2]) + "\"/>");
+	}
+
+	// Normal
+	if(getTexture(mtl, "normalTexture", fname))
+	{
+		xml = replaceAllString(
+			xml, "%normal%", "<input shaderInput=\"normalTex\" value=\"" + std::string(fname.cstr()) + "\"/>");
+		xml = replaceAllString(xml, "%normalTexMutator%", "1");
+	}
+	else
+	{
+		xml = replaceAllString(xml, "%normal%", "");
+		xml = replaceAllString(xml, "%normalTexMutator%", "0");
+	}
+
+	// Roughness & metallic
+	I metallic = -1;
+	I roughness = -1;
+	if(getTexture(mtl, "metallicRoughnessTexture", fname))
+	{
+		if(fname.find("_rm.") != String::NPOS)
+		{
+			roughness = 0;
+			metallic = 1;
+		}
+		else if(fname.find("_r.") != String::NPOS)
+		{
+			roughness = 0;
+		}
+		else if(fname.find("_m.") != String::NPOS)
+		{
+			metallic = 0;
+		}
+		else
+		{
+			ANKI_LOGE("Can't identify the type of metallicRoughnessTexture by its filename");
+			return Error::USER_DATA;
+		}
+
+		if(metallic > -1)
+		{
+			xml = replaceAllString(
+				xml, "%metallic%", "<input shaderInput=\"metalTex\" value=\"" + std::string(fname.cstr()) + "\"/>");
+			xml = replaceAllString(xml, "%metalTexMutator%", std::to_string(metallic + 1));
+		}
+
+		if(roughness > -1)
+		{
+			xml = replaceAllString(xml,
+				"%roughness%",
+				"<input shaderInput=\"roughnessTex\" value=\"" + std::string(fname.cstr()) + "\"/>");
+			xml = replaceAllString(xml, "%roughnessTexMutator%", std::to_string(roughness + 1));
+		}
+	}
+
+	if(metallic == -1)
+	{
+		EXPORT_ASSERT(getMaterialAttrib(mtl, "metallicFactor", v4));
+		xml = replaceAllString(
+			xml, "%metallic%", "<input shaderInput=\"metallic\" value=\"" + std::to_string(v4.x()) + "\"/>");
+
+		xml = replaceAllString(xml, "%metalTexMutator%", "0");
+	}
+
+	if(roughness == -1)
+	{
+		EXPORT_ASSERT(getMaterialAttrib(mtl, "roughnessFactor", v4));
+
+		xml = replaceAllString(
+			xml, "%roughness%", "<input shaderInput=\"roughness\" value=\"" + std::to_string(v4.x()) + "\" />");
+
+		xml = replaceAllString(xml, "%roughnessTexMutator%", "0");
+	}
+
+	// Replace texture extensions with .anki
+	xml = replaceAllString(xml, ".tga", ".ankitex");
+	xml = replaceAllString(xml, ".png", ".ankitex");
+	xml = replaceAllString(xml, ".jpg", ".ankitex");
+	xml = replaceAllString(xml, ".jpeg", ".ankitex");
+
 	return Error::NONE;
 }
 

+ 2 - 1
tools/gltf_exporter/Exporter.h

@@ -43,7 +43,8 @@ private:
 
 	Error exportMaterial(const tinygltf::Material& mtl);
 
-	void getTexture(tinygltf::Material& mtl, CString texName, CString& fname) const;
+	Bool getTexture(const tinygltf::Material& mtl, CString texName, StringAuto& fname) const;
+	Bool getMaterialAttrib(const tinygltf::Material& mtl, CString attribName, Vec4& value) const;
 };
 
 #define EXPORT_ASSERT(expr) \

+ 17 - 0
tools/gltf_exporter/TinyGltf.cpp

@@ -0,0 +1,17 @@
+// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#if defined(__GNUC__)
+#	pragma GCC diagnostic push
+#	pragma GCC diagnostic ignored "-Wmisleading-indentation"
+#	pragma GCC diagnostic ignored "-Wshift-negative-value"
+#endif
+#define TINYGLTF_IMPLEMENTATION
+#define STB_IMAGE_IMPLEMENTATION
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+#include <tinygltf/tiny_gltf.h>
+#if defined(__GNUC__)
+#	pragma GCC diagnostic pop
+#endif