Procházet zdrojové kódy

Updated meshoptimizer.

Бранимир Караџић před 6 roky
rodič
revize
126c0d6596

+ 3 - 1
3rdparty/meshoptimizer/.github/workflows/build.yml

@@ -17,6 +17,7 @@ jobs:
         make -j2 config=debug test
         make -j2 config=release test
         make -j2 config=release gltfpack
+        strip gltfpack
     - name: make coverage
       run: |
         make -j2 config=coverage test
@@ -36,7 +37,7 @@ jobs:
     steps:
     - uses: actions/checkout@v1
     - name: cmake configure
-      run: cmake . -DBUILD_DEMO=ON -DBUILD_TOOLS=ON -A ${{matrix.arch}}
+      run: cmake . -DBUILD_DEMO=ON -DBUILD_TOOLS=ON -DCMAKE_MSVC_RUNTIME_LIBRARY="MultiThreaded$<$<CONFIG:Debug>:Debug>" -A ${{matrix.arch}}
     - name: cmake test
       shell: bash # necessary for fail-fast
       run: |
@@ -48,3 +49,4 @@ jobs:
       with:
         name: gltfpack-windows
         path: Release/gltfpack.exe
+      if: matrix.arch == 'x64'

+ 1 - 0
3rdparty/meshoptimizer/.travis.yml

@@ -1,6 +1,7 @@
 language: cpp
 
 jobs:
+  include:
   - os: linux
     compiler: gcc
   - os: linux

+ 5 - 0
3rdparty/meshoptimizer/CMakeLists.txt

@@ -1,5 +1,10 @@
 cmake_minimum_required(VERSION 3.0)
 
+if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.15)
+    cmake_policy(SET CMP0091 NEW) # Enables use of MSVC_RUNTIME_LIBRARY
+    cmake_policy(SET CMP0092 NEW) # Enables clean /W4 override for MSVC
+endif()
+
 project(meshoptimizer VERSION 0.12 LANGUAGES CXX)
 
 option(BUILD_DEMO "Build demo" OFF)

+ 1 - 0
3rdparty/meshoptimizer/demo/demo.html

@@ -33,6 +33,7 @@
         var canvas = document.getElementById("renderCanvas");
 
         BABYLON.GLTF2.GLTFLoader.RegisterExtension("MESHOPT_compression", (loader) => new MESHOPT_compression(loader, MeshoptDecoder));
+        BABYLON.GLTF2.GLTFLoader.RegisterExtension("KHR_quantized_geometry", (loader) => ({ name: "KHR_quantized_geometry", enabled: true }));
 
         var createScene = function () {
             var scene = new BABYLON.Scene(engine);

binární
3rdparty/meshoptimizer/demo/pirate.glb


+ 83 - 25
3rdparty/meshoptimizer/tools/gltfpack.cpp

@@ -73,7 +73,7 @@ struct Settings
 	int pos_bits;
 	int tex_bits;
 	int nrm_bits;
-	bool nrm_unit;
+	bool nrm_unnormalized;
 
 	int anim_freq;
 	bool anim_const;
@@ -841,6 +841,29 @@ void reindexMesh(Mesh& mesh)
 	}
 }
 
+void filterMesh(Mesh& mesh)
+{
+	unsigned int* indices = &mesh.indices[0];
+	size_t total_indices = mesh.indices.size();
+
+	size_t write = 0;
+
+	for (size_t i = 0; i < total_indices; i += 3)
+	{
+		unsigned int a = indices[i + 0], b = indices[i + 1], c = indices[i + 2];
+
+		if (a != b && a != c && b != c)
+		{
+			indices[write + 0] = a;
+			indices[write + 1] = b;
+			indices[write + 2] = c;
+			write += 3;
+		}
+	}
+
+	mesh.indices.resize(write);
+}
+
 Stream* getStream(Mesh& mesh, cgltf_attribute_type type)
 {
 	for (size_t i = 0; i < mesh.streams.size(); ++i)
@@ -922,6 +945,9 @@ void sortBoneInfluences(Mesh& mesh)
 	if (!joints || !weights)
 		return;
 
+	// weights below cutoff can't be represented in quantized 8-bit storage
+	const float weight_cutoff = 0.5f / 255.f;
+
 	size_t vertex_count = mesh.streams[0].data.size();
 
 	for (size_t i = 0; i < vertex_count; ++i)
@@ -933,7 +959,7 @@ void sortBoneInfluences(Mesh& mesh)
 		int count = 0;
 
 		for (int k = 0; k < 4; ++k)
-			if (wa.f[k] > 0.f)
+			if (wa.f[k] > weight_cutoff)
 			{
 				inf[count].i = ja.f[k];
 				inf[count].w = wa.f[k];
@@ -1156,20 +1182,51 @@ StreamFormat writeVertexStream(std::string& bin, const Stream& stream, const Qua
 		{
 			float pos_rscale = params.pos_scale == 0.f ? 0.f : 1.f / params.pos_scale;
 
+			int maxv = 0;
+
 			for (size_t i = 0; i < stream.data.size(); ++i)
 			{
 				const Attr& a = stream.data[i];
 
-				int16_t v[4] = {
-				    int16_t((a.f[0] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[0]) * pos_rscale, params.pos_bits)),
-				    int16_t((a.f[1] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[1]) * pos_rscale, params.pos_bits)),
-				    int16_t((a.f[2] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[2]) * pos_rscale, params.pos_bits)),
-				    0};
-				bin.append(reinterpret_cast<const char*>(v), sizeof(v));
+				maxv = std::max(maxv, meshopt_quantizeUnorm(fabsf(a.f[0]) * pos_rscale, params.pos_bits));
+				maxv = std::max(maxv, meshopt_quantizeUnorm(fabsf(a.f[1]) * pos_rscale, params.pos_bits));
+				maxv = std::max(maxv, meshopt_quantizeUnorm(fabsf(a.f[2]) * pos_rscale, params.pos_bits));
 			}
 
-			StreamFormat format = {cgltf_type_vec3, cgltf_component_type_r_16, false, 8};
-			return format;
+			if (maxv <= 127)
+			{
+				for (size_t i = 0; i < stream.data.size(); ++i)
+				{
+					const Attr& a = stream.data[i];
+
+					int8_t v[4] = {
+					    int8_t((a.f[0] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[0]) * pos_rscale, params.pos_bits)),
+					    int8_t((a.f[1] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[1]) * pos_rscale, params.pos_bits)),
+					    int8_t((a.f[2] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[2]) * pos_rscale, params.pos_bits)),
+					    0};
+					bin.append(reinterpret_cast<const char*>(v), sizeof(v));
+				}
+
+				StreamFormat format = {cgltf_type_vec3, cgltf_component_type_r_8, false, 4};
+				return format;
+			}
+			else
+			{
+				for (size_t i = 0; i < stream.data.size(); ++i)
+				{
+					const Attr& a = stream.data[i];
+
+					int16_t v[4] = {
+					    int16_t((a.f[0] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[0]) * pos_rscale, params.pos_bits)),
+					    int16_t((a.f[1] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[1]) * pos_rscale, params.pos_bits)),
+					    int16_t((a.f[2] >= 0.f ? 1 : -1) * meshopt_quantizeUnorm(fabsf(a.f[2]) * pos_rscale, params.pos_bits)),
+					    0};
+					bin.append(reinterpret_cast<const char*>(v), sizeof(v));
+				}
+
+				StreamFormat format = {cgltf_type_vec3, cgltf_component_type_r_16, false, 8};
+				return format;
+			}
 		}
 	}
 	else if (stream.type == cgltf_attribute_type_texcoord)
@@ -1195,8 +1252,8 @@ StreamFormat writeVertexStream(std::string& bin, const Stream& stream, const Qua
 	}
 	else if (stream.type == cgltf_attribute_type_normal)
 	{
-		bool nrm_unit = has_targets || settings.nrm_unit;
-		int bits = nrm_unit ? (settings.nrm_bits > 8 ? 16 : 8) : settings.nrm_bits;
+		bool unnormalized = settings.nrm_unnormalized && !has_targets;
+		int bits = unnormalized ? settings.nrm_bits : (settings.nrm_bits > 8 ? 16 : 8);
 
 		for (size_t i = 0; i < stream.data.size(); ++i)
 		{
@@ -1204,7 +1261,7 @@ StreamFormat writeVertexStream(std::string& bin, const Stream& stream, const Qua
 
 			float nx = a.f[0], ny = a.f[1], nz = a.f[2];
 
-			if (!nrm_unit)
+			if (unnormalized)
 				rescaleNormal(nx, ny, nz);
 
 			if (bits > 8)
@@ -1240,8 +1297,8 @@ StreamFormat writeVertexStream(std::string& bin, const Stream& stream, const Qua
 	}
 	else if (stream.type == cgltf_attribute_type_tangent)
 	{
-		bool nrm_unit = has_targets || settings.nrm_unit;
-		int bits = nrm_unit ? (settings.nrm_bits > 8 ? 16 : 8) : settings.nrm_bits;
+		bool unnormalized = settings.nrm_unnormalized && !has_targets;
+		int bits = unnormalized ? settings.nrm_bits : (settings.nrm_bits > 8 ? 16 : 8);
 
 		for (size_t i = 0; i < stream.data.size(); ++i)
 		{
@@ -1249,7 +1306,7 @@ StreamFormat writeVertexStream(std::string& bin, const Stream& stream, const Qua
 
 			float nx = a.f[0], ny = a.f[1], nz = a.f[2], nw = a.f[3];
 
-			if (!nrm_unit)
+			if (unnormalized)
 				rescaleNormal(nx, ny, nz);
 
 			if (bits > 8)
@@ -3143,6 +3200,7 @@ void process(cgltf_data* data, std::vector<Mesh>& meshes, const Settings& settin
 
 		case cgltf_primitive_type_triangles:
 			reindexMesh(mesh);
+			filterMesh(mesh);
 			simplifyMesh(mesh, settings.simplify_threshold, settings.simplify_aggressive);
 			optimizeMesh(mesh);
 			sortBoneInfluences(mesh);
@@ -3443,8 +3501,9 @@ void process(cgltf_data* data, std::vector<Mesh>& meshes, const Settings& settin
 		json.append(data->json + data->asset.extras.start_offset, data->json + data->asset.extras.end_offset);
 	}
 	append(json, "}");
+
 	append(json, ",\"extensionsUsed\":[");
-	append(json, "\"MESHOPT_quantized_geometry\"");
+	append(json, "\"KHR_quantized_geometry\"");
 	if (settings.compress)
 	{
 		comma(json);
@@ -3471,16 +3530,15 @@ void process(cgltf_data* data, std::vector<Mesh>& meshes, const Settings& settin
 		append(json, "\"KHR_lights_punctual\"");
 	}
 	append(json, "]");
+
+	append(json, ",\"extensionsRequired\":[");
+	append(json, "\"KHR_quantized_geometry\"");
 	if (settings.compress && !settings.fallback)
 	{
-		append(json, ",\"extensionsRequired\":[");
-		// Note: ideally we should include MESHOPT_quantized_geometry in the required extension list (regardless of compression)
-		// This extension *only* allows the use of quantized attributes for positions/normals/etc. This happens to be supported
-		// by popular JS frameworks, however, Babylon.JS refuses to load files with unsupported required extensions.
-		// For now we don't include it in the list, which will be fixed at some point once this extension becomes official.
+		comma(json);
 		append(json, "\"MESHOPT_compression\"");
-		append(json, "]");
 	}
+	append(json, "]");
 
 	if (!views.empty())
 	{
@@ -3833,7 +3891,7 @@ int main(int argc, char** argv)
 		}
 		else if (strcmp(arg, "-vu") == 0)
 		{
-			settings.nrm_unit = true;
+			settings.nrm_unnormalized = true;
 		}
 		else if (strcmp(arg, "-af") == 0 && i + 1 < argc && isdigit(argv[i + 1][0]))
 		{
@@ -3917,7 +3975,7 @@ int main(int argc, char** argv)
 		fprintf(stderr, "-vp N: use N-bit quantization for positions (default: 14; N should be between 1 and 16)\n");
 		fprintf(stderr, "-vt N: use N-bit quantization for texture corodinates (default: 12; N should be between 1 and 16)\n");
 		fprintf(stderr, "-vn N: use N-bit quantization for normals and tangents (default: 8; N should be between 1 and 16)\n");
-		fprintf(stderr, "-vu: use unit-length normal/tangent vectors (default: off)\n");
+		fprintf(stderr, "-vu: use unnormalized normal/tangent vectors to improve compression (default: off)\n");
 		fprintf(stderr, "-af N: resample animations at N Hz (default: 30)\n");
 		fprintf(stderr, "-ac: keep constant animation tracks even if they don't modify the node transform\n");
 		fprintf(stderr, "-kn: keep named nodes and meshes attached to named nodes so that named nodes can be transformed externally\n");