Browse Source

xatlas: Sync with upstream 5571fc7

Fixes #44017 by changing the `normalize()` function to check for non-negative rather than non-zero via an epsilon check.
Adam Brown 4 years ago
parent
commit
23c754360a
4 changed files with 299 additions and 466 deletions
  1. 3 3
      modules/xatlas_unwrap/register_types.cpp
  2. 1 1
      thirdparty/README.md
  3. 217 370
      thirdparty/xatlas/xatlas.cpp
  4. 78 92
      thirdparty/xatlas/xatlas.h

+ 3 - 3
modules/xatlas_unwrap/register_types.cpp

@@ -141,11 +141,11 @@ bool xatlas_mesh_lightmap_unwrap_callback(float p_texel_size, const float *p_ver
 
 
 	xatlas::Atlas *atlas = xatlas::Create();
 	xatlas::Atlas *atlas = xatlas::Create();
 	printf("Adding mesh..\n");
 	printf("Adding mesh..\n");
-	xatlas::AddMeshError::Enum err = xatlas::AddMesh(atlas, input_mesh, 1);
-	ERR_FAIL_COND_V_MSG(err != xatlas::AddMeshError::Enum::Success, false, xatlas::StringForEnum(err));
+	xatlas::AddMeshError err = xatlas::AddMesh(atlas, input_mesh, 1);
+	ERR_FAIL_COND_V_MSG(err != xatlas::AddMeshError::Success, false, xatlas::StringForEnum(err));
 
 
 	printf("Generate..\n");
 	printf("Generate..\n");
-	xatlas::Generate(atlas, chart_options, xatlas::ParameterizeOptions(), pack_options);
+	xatlas::Generate(atlas, chart_options, xatlas::PackOptions());
 
 
 	*r_size_hint_x = atlas->width;
 	*r_size_hint_x = atlas->width;
 	*r_size_hint_y = atlas->height;
 	*r_size_hint_y = atlas->height;

+ 1 - 1
thirdparty/README.md

@@ -671,7 +671,7 @@ File extracted from upstream release tarball:
 ## xatlas
 ## xatlas
 
 
 - Upstream: https://github.com/jpcy/xatlas
 - Upstream: https://github.com/jpcy/xatlas
-- Version: git (470576d3516f7e6d8b4554e7c941194a935969fd, 2020)
+- Version: git (5571fc7ef0d06832947c0a935ccdcf083f7a9264, 2020)
 - License: MIT
 - License: MIT
 
 
 Files extracted from upstream source:
 Files extracted from upstream source:

File diff suppressed because it is too large
+ 217 - 370
thirdparty/xatlas/xatlas.cpp


+ 78 - 92
thirdparty/xatlas/xatlas.h

@@ -31,35 +31,30 @@ Copyright NVIDIA Corporation 2006 -- Ignacio Castano <[email protected]>
 #pragma once
 #pragma once
 #ifndef XATLAS_H
 #ifndef XATLAS_H
 #define XATLAS_H
 #define XATLAS_H
+#include <stddef.h>
 #include <stdint.h>
 #include <stdint.h>
 
 
 namespace xatlas {
 namespace xatlas {
 
 
-struct ChartType
-{
-	enum Enum
-	{
-		Planar,
-		Ortho,
-		LSCM,
-		Piecewise,
-		Invalid
-	};
+enum class ChartType {
+	Planar,
+	Ortho,
+	LSCM,
+	Piecewise,
+	Invalid
 };
 };
 
 
 // A group of connected faces, belonging to a single atlas.
 // A group of connected faces, belonging to a single atlas.
-struct Chart
-{
+struct Chart {
 	uint32_t *faceArray;
 	uint32_t *faceArray;
 	uint32_t atlasIndex; // Sub-atlas index.
 	uint32_t atlasIndex; // Sub-atlas index.
 	uint32_t faceCount;
 	uint32_t faceCount;
-	ChartType::Enum type;
+	ChartType type;
 	uint32_t material;
 	uint32_t material;
 };
 };
 
 
 // Output vertex.
 // Output vertex.
-struct Vertex
-{
+struct Vertex {
 	int32_t atlasIndex; // Sub-atlas index. -1 if the vertex doesn't exist in any atlas.
 	int32_t atlasIndex; // Sub-atlas index. -1 if the vertex doesn't exist in any atlas.
 	int32_t chartIndex; // -1 if the vertex doesn't exist in any chart.
 	int32_t chartIndex; // -1 if the vertex doesn't exist in any chart.
 	float uv[2]; // Not normalized - values are in Atlas width and height range.
 	float uv[2]; // Not normalized - values are in Atlas width and height range.
@@ -67,8 +62,7 @@ struct Vertex
 };
 };
 
 
 // Output mesh.
 // Output mesh.
-struct Mesh
-{
+struct Mesh {
 	Chart *chartArray;
 	Chart *chartArray;
 	uint32_t *indexArray;
 	uint32_t *indexArray;
 	Vertex *vertexArray;
 	Vertex *vertexArray;
@@ -83,16 +77,15 @@ static const uint32_t kImageIsBilinearBit = 0x40000000;
 static const uint32_t kImageIsPaddingBit = 0x20000000;
 static const uint32_t kImageIsPaddingBit = 0x20000000;
 
 
 // Empty on creation. Populated after charts are packed.
 // Empty on creation. Populated after charts are packed.
-struct Atlas
-{
+struct Atlas {
 	uint32_t *image;
 	uint32_t *image;
 	Mesh *meshes; // The output meshes, corresponding to each AddMesh call.
 	Mesh *meshes; // The output meshes, corresponding to each AddMesh call.
+	float *utilization; // Normalized atlas texel utilization array. E.g. a value of 0.8 means 20% empty space. atlasCount in length.
 	uint32_t width; // Atlas width in texels.
 	uint32_t width; // Atlas width in texels.
 	uint32_t height; // Atlas height in texels.
 	uint32_t height; // Atlas height in texels.
 	uint32_t atlasCount; // Number of sub-atlases. Equal to 0 unless PackOptions resolution is changed from default (0).
 	uint32_t atlasCount; // Number of sub-atlases. Equal to 0 unless PackOptions resolution is changed from default (0).
 	uint32_t chartCount; // Total number of charts in all meshes.
 	uint32_t chartCount; // Total number of charts in all meshes.
 	uint32_t meshCount; // Number of output meshes. Equal to the number of times AddMesh was called.
 	uint32_t meshCount; // Number of output meshes. Equal to the number of times AddMesh was called.
-	float *utilization; // Normalized atlas texel utilization array. E.g. a value of 0.8 means 20% empty space. atlasCount in length.
 	float texelsPerUnit; // Equal to PackOptions texelsPerUnit if texelsPerUnit > 0, otherwise an estimated value to match PackOptions resolution.
 	float texelsPerUnit; // Equal to PackOptions texelsPerUnit if texelsPerUnit > 0, otherwise an estimated value to match PackOptions resolution.
 };
 };
 
 
@@ -101,73 +94,76 @@ Atlas *Create();
 
 
 void Destroy(Atlas *atlas);
 void Destroy(Atlas *atlas);
 
 
-struct IndexFormat
-{
-	enum Enum
-	{
-		UInt16,
-		UInt32
-	};
+enum class IndexFormat {
+	UInt16,
+	UInt32
 };
 };
 
 
 // Input mesh declaration.
 // Input mesh declaration.
-struct MeshDecl
-{
+struct MeshDecl {
 	const void *vertexPositionData = nullptr;
 	const void *vertexPositionData = nullptr;
 	const void *vertexNormalData = nullptr; // optional
 	const void *vertexNormalData = nullptr; // optional
 	const void *vertexUvData = nullptr; // optional. The input UVs are provided as a hint to the chart generator.
 	const void *vertexUvData = nullptr; // optional. The input UVs are provided as a hint to the chart generator.
 	const void *indexData = nullptr; // optional
 	const void *indexData = nullptr; // optional
-	
-	// Optional. indexCount / 3 (triangle count) in length.
+
+	// Optional. Must be faceCount in length.
 	// Don't atlas faces set to true. Ignored faces still exist in the output meshes, Vertex uv is set to (0, 0) and Vertex atlasIndex to -1.
 	// Don't atlas faces set to true. Ignored faces still exist in the output meshes, Vertex uv is set to (0, 0) and Vertex atlasIndex to -1.
 	const bool *faceIgnoreData = nullptr;
 	const bool *faceIgnoreData = nullptr;
 
 
+	// Optional. Must be faceCount in length.
+	// Only faces with the same material will be assigned to the same chart.
+	const uint32_t *faceMaterialData = nullptr;
+
+	// Optional. Must be faceCount in length.
+	// Polygon / n-gon support. Faces are assumed to be triangles if this is null.
+	const uint8_t *faceVertexCount = nullptr;
+
 	uint32_t vertexCount = 0;
 	uint32_t vertexCount = 0;
 	uint32_t vertexPositionStride = 0;
 	uint32_t vertexPositionStride = 0;
 	uint32_t vertexNormalStride = 0; // optional
 	uint32_t vertexNormalStride = 0; // optional
 	uint32_t vertexUvStride = 0; // optional
 	uint32_t vertexUvStride = 0; // optional
 	uint32_t indexCount = 0;
 	uint32_t indexCount = 0;
 	int32_t indexOffset = 0; // optional. Add this offset to all indices.
 	int32_t indexOffset = 0; // optional. Add this offset to all indices.
-	IndexFormat::Enum indexFormat = IndexFormat::UInt16;
+	uint32_t faceCount = 0; // Optional if faceVertexCount is null. Otherwise assumed to be indexCount / 3.
+	IndexFormat indexFormat = IndexFormat::UInt16;
 
 
 	// Vertex positions within epsilon distance of each other are considered colocal.
 	// Vertex positions within epsilon distance of each other are considered colocal.
 	float epsilon = 1.192092896e-07F;
 	float epsilon = 1.192092896e-07F;
 };
 };
 
 
-struct AddMeshError
-{
-	enum Enum
-	{
-		Success, // No error.
-		Error, // Unspecified error.
-		IndexOutOfRange, // An index is >= MeshDecl vertexCount.
-		InvalidIndexCount // Not evenly divisible by 3 - expecting triangles.
-	};
+enum class AddMeshError {
+	Success, // No error.
+	Error, // Unspecified error.
+	IndexOutOfRange, // An index is >= MeshDecl vertexCount.
+	InvalidFaceVertexCount, // Must be >= 3.
+	InvalidIndexCount // Not evenly divisible by 3 - expecting triangles.
 };
 };
 
 
 // Add a mesh to the atlas. MeshDecl data is copied, so it can be freed after AddMesh returns.
 // Add a mesh to the atlas. MeshDecl data is copied, so it can be freed after AddMesh returns.
-AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint = 0);
+AddMeshError AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint = 0);
 
 
 // Wait for AddMesh async processing to finish. ComputeCharts / Generate call this internally.
 // Wait for AddMesh async processing to finish. ComputeCharts / Generate call this internally.
 void AddMeshJoin(Atlas *atlas);
 void AddMeshJoin(Atlas *atlas);
 
 
-struct UvMeshDecl
-{
+struct UvMeshDecl {
 	const void *vertexUvData = nullptr;
 	const void *vertexUvData = nullptr;
 	const void *indexData = nullptr; // optional
 	const void *indexData = nullptr; // optional
-	const uint32_t *faceMaterialData = nullptr; // Optional. Faces with different materials won't be assigned to the same chart. Must be indexCount / 3 in length.
+	const uint32_t *faceMaterialData = nullptr; // Optional. Overlapping UVs should be assigned a different material. Must be indexCount / 3 in length.
 	uint32_t vertexCount = 0;
 	uint32_t vertexCount = 0;
 	uint32_t vertexStride = 0;
 	uint32_t vertexStride = 0;
 	uint32_t indexCount = 0;
 	uint32_t indexCount = 0;
 	int32_t indexOffset = 0; // optional. Add this offset to all indices.
 	int32_t indexOffset = 0; // optional. Add this offset to all indices.
-	IndexFormat::Enum indexFormat = IndexFormat::UInt16;
-	bool rotateCharts = true;
+	IndexFormat indexFormat = IndexFormat::UInt16;
 };
 };
 
 
-AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl);
+AddMeshError AddUvMesh(Atlas *atlas, const UvMeshDecl &decl);
+
+// Custom parameterization function. texcoords initial values are an orthogonal parameterization.
+typedef void (*ParameterizeFunc)(const float *positions, float *texcoords, uint32_t vertexCount, const uint32_t *indices, uint32_t indexCount);
+
+struct ChartOptions {
+	ParameterizeFunc paramFunc = nullptr;
 
 
-struct ChartOptions
-{
 	float maxChartArea = 0.0f; // Don't grow charts to be larger than this. 0 means no limit.
 	float maxChartArea = 0.0f; // Don't grow charts to be larger than this. 0 means no limit.
 	float maxBoundaryLength = 0.0f; // Don't grow charts to have a longer boundary than this. 0 means no limit.
 	float maxBoundaryLength = 0.0f; // Don't grow charts to have a longer boundary than this. 0 means no limit.
 
 
@@ -180,26 +176,31 @@ struct ChartOptions
 
 
 	float maxCost = 2.0f; // If total of all metrics * weights > maxCost, don't grow chart. Lower values result in more charts.
 	float maxCost = 2.0f; // If total of all metrics * weights > maxCost, don't grow chart. Lower values result in more charts.
 	uint32_t maxIterations = 1; // Number of iterations of the chart growing and seeding phases. Higher values result in better charts.
 	uint32_t maxIterations = 1; // Number of iterations of the chart growing and seeding phases. Higher values result in better charts.
+
+	bool useInputMeshUvs = false; // Use MeshDecl::vertexUvData for charts.
+	bool fixWinding = false; // Enforce consistent texture coordinate winding.
 };
 };
 
 
 // Call after all AddMesh calls. Can be called multiple times to recompute charts with different options.
 // Call after all AddMesh calls. Can be called multiple times to recompute charts with different options.
 void ComputeCharts(Atlas *atlas, ChartOptions options = ChartOptions());
 void ComputeCharts(Atlas *atlas, ChartOptions options = ChartOptions());
 
 
-// Custom parameterization function. texcoords initial values are an orthogonal parameterization.
-typedef void (*ParameterizeFunc)(const float *positions, float *texcoords, uint32_t vertexCount, const uint32_t *indices, uint32_t indexCount);
+struct PackOptions {
+	// Charts larger than this will be scaled down. 0 means no limit.
+	uint32_t maxChartSize = 0;
 
 
-struct ParameterizeOptions
-{
-	ParameterizeFunc func = nullptr;
-	bool closeHoles = true; // If the custom parameterization function works with multiple boundaries, this can be set to false to improve performance.
-	bool fixTJunctions = true; // If meshes don't have T-junctions, this can be set to false to improve performance.
-};
+	// Number of pixels to pad charts with.
+	uint32_t padding = 0;
+
+	// Unit to texel scale. e.g. a 1x1 quad with texelsPerUnit of 32 will take up approximately 32x32 texels in the atlas.
+	// If 0, an estimated value will be calculated to approximately match the given resolution.
+	// If resolution is also 0, the estimated value will approximately match a 1024x1024 atlas.
+	float texelsPerUnit = 0.0f;
 
 
-// Call after ComputeCharts. Can be called multiple times to re-parameterize charts with a different ParameterizeFunc.
-void ParameterizeCharts(Atlas *atlas, ParameterizeOptions options = ParameterizeOptions());
+	// If 0, generate a single atlas with texelsPerUnit determining the final resolution.
+	// If not 0, and texelsPerUnit is not 0, generate one or more atlases with that exact resolution.
+	// If not 0, and texelsPerUnit is 0, texelsPerUnit is estimated to approximately match the resolution.
+	uint32_t resolution = 0;
 
 
-struct PackOptions
-{
 	// Leave space around charts for texels that would be sampled by bilinear filtering.
 	// Leave space around charts for texels that would be sampled by bilinear filtering.
 	bool bilinear = true;
 	bool bilinear = true;
 
 
@@ -212,44 +213,29 @@ struct PackOptions
 	// Create Atlas::image
 	// Create Atlas::image
 	bool createImage = false;
 	bool createImage = false;
 
 
-	// Charts larger than this will be scaled down. 0 means no limit.
-	uint32_t maxChartSize = 0;
-
-	// Number of pixels to pad charts with.
-	uint32_t padding = 0;
+	// Rotate charts to the axis of their convex hull.
+	bool rotateChartsToAxis = true;
 
 
-	// Unit to texel scale. e.g. a 1x1 quad with texelsPerUnit of 32 will take up approximately 32x32 texels in the atlas.
-	// If 0, an estimated value will be calculated to approximately match the given resolution.
-	// If resolution is also 0, the estimated value will approximately match a 1024x1024 atlas.
-	float texelsPerUnit = 0.0f;
-
-	// If 0, generate a single atlas with texelsPerUnit determining the final resolution.
-	// If not 0, and texelsPerUnit is not 0, generate one or more atlases with that exact resolution.
-	// If not 0, and texelsPerUnit is 0, texelsPerUnit is estimated to approximately match the resolution.
-	uint32_t resolution = 0;
+	// Rotate charts to improve packing.
+	bool rotateCharts = true;
 };
 };
 
 
-// Call after ParameterizeCharts. Can be called multiple times to re-pack charts with different options.
+// Call after ComputeCharts. Can be called multiple times to re-pack charts with different options.
 void PackCharts(Atlas *atlas, PackOptions packOptions = PackOptions());
 void PackCharts(Atlas *atlas, PackOptions packOptions = PackOptions());
 
 
-// Equivalent to calling ComputeCharts, ParameterizeCharts and PackCharts in sequence. Can be called multiple times to regenerate with different options.
-void Generate(Atlas *atlas, ChartOptions chartOptions = ChartOptions(), ParameterizeOptions parameterizeOptions = ParameterizeOptions(), PackOptions packOptions = PackOptions());
+// Equivalent to calling ComputeCharts and PackCharts in sequence. Can be called multiple times to regenerate with different options.
+void Generate(Atlas *atlas, ChartOptions chartOptions = ChartOptions(), PackOptions packOptions = PackOptions());
 
 
 // Progress tracking.
 // Progress tracking.
-struct ProgressCategory
-{
-	enum Enum
-	{
-		AddMesh,
-		ComputeCharts,
-		ParameterizeCharts,
-		PackCharts,
-		BuildOutputMeshes
-	};
+enum class ProgressCategory {
+	AddMesh,
+	ComputeCharts,
+	PackCharts,
+	BuildOutputMeshes
 };
 };
 
 
 // May be called from any thread. Return false to cancel.
 // May be called from any thread. Return false to cancel.
-typedef bool (*ProgressFunc)(ProgressCategory::Enum category, int progress, void *userData);
+typedef bool (*ProgressFunc)(ProgressCategory category, int progress, void *userData);
 
 
 void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc = nullptr, void *progressUserData = nullptr);
 void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc = nullptr, void *progressUserData = nullptr);
 
 
@@ -263,8 +249,8 @@ typedef int (*PrintFunc)(const char *, ...);
 void SetPrint(PrintFunc print, bool verbose);
 void SetPrint(PrintFunc print, bool verbose);
 
 
 // Helper functions for error messages.
 // Helper functions for error messages.
-const char *StringForEnum(AddMeshError::Enum error);
-const char *StringForEnum(ProgressCategory::Enum category);
+const char *StringForEnum(AddMeshError error);
+const char *StringForEnum(ProgressCategory category);
 
 
 } // namespace xatlas
 } // namespace xatlas
 
 

Some files were not shown because too many files changed in this diff