summaryrefslogtreecommitdiff
path: root/thirdparty/xatlas/xatlas.h
blob: dbf8ca08c77dea1d8ea5d8b2aef7113039c3eaaf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// This code is in the public domain -- castanyo@yahoo.es
#pragma once
#ifndef XATLAS_H
#define XATLAS_H
#include <float.h> // FLT_MAX
// -- GODOT start --
#include <limits.h> // INT_MAX, UINT_MAX
// -- GODOT end --

namespace xatlas {

typedef void (*PrintFunc)(const char *, ...);

struct Atlas;

struct CharterOptions
{
	float proxyFitMetricWeight;
	float roundnessMetricWeight;
	float straightnessMetricWeight;
	float normalSeamMetricWeight;
	float textureSeamMetricWeight;
	float maxChartArea;
	float maxBoundaryLength;

	CharterOptions()
	{
		// These are the default values we use on The Witness.
		proxyFitMetricWeight = 2.0f;
		roundnessMetricWeight = 0.01f;
		straightnessMetricWeight = 6.0f;
		normalSeamMetricWeight = 4.0f;
		textureSeamMetricWeight = 0.5f;
		/*
		proxyFitMetricWeight = 1.0f;
		roundnessMetricWeight = 0.1f;
		straightnessMetricWeight = 0.25f;
		normalSeamMetricWeight = 1.0f;
		textureSeamMetricWeight = 0.1f;
		*/
		maxChartArea = FLT_MAX;
		maxBoundaryLength = FLT_MAX;
	}
};

struct PackMethod
{
	enum Enum
	{
		TexelArea, // texel_area determines resolution
		ApproximateResolution, // guess texel_area to approximately match desired resolution
		ExactResolution // run the packer multiple times to exactly match the desired resolution (slow)
	};
};

struct PackerOptions
{
	PackMethod::Enum method;

	// 0 - brute force
	// 1 - 4096 attempts
	// 2 - 2048
	// 3 - 1024
	// 4 - 512
	// other - 256
	// Avoid brute force packing, since it can be unusably slow in some situations.
	int quality;

	float texelArea;       // This is not really texel area, but 1 / texel width?
	uint32_t resolution;
	bool blockAlign;       // Align charts to 4x4 blocks. 
	bool conservative;      // Pack charts with extra padding.
	int padding;

	PackerOptions()
	{
		method = PackMethod::ApproximateResolution;
		quality = 1;
		texelArea = 8;
		resolution = 512;
		blockAlign = false;
		conservative = false;
		padding = 0;
	}
};

struct AddMeshErrorCode
{
	enum Enum
	{
		Success,
		AlreadyAddedEdge, // index0 and index1 are the edge indices
		DegenerateColocalEdge, // index0 and index1 are the edge indices
		DegenerateEdge, // index0 and index1 are the edge indices
		DuplicateEdge, // index0 and index1 are the edge indices
		IndexOutOfRange, // index0 is the index
		InvalidIndexCount, // not evenly divisible by 3 - expecting triangles
		ZeroAreaFace,
		ZeroLengthEdge // index0 and index1 are the edge indices
	};
};

struct AddMeshError
{
	AddMeshErrorCode::Enum code;
	uint32_t face;
	uint32_t index0, index1;
};

struct IndexFormat
{
	enum Enum
	{
		HalfFloat,
		Float
	};
};

struct InputMesh
{
	uint32_t vertexCount;
	const void *vertexPositionData;
	uint32_t vertexPositionStride;
	const void *vertexNormalData; // optional
	uint32_t vertexNormalStride; // optional

	// optional
	// The input UVs are provided as a hint to the chart generator.
	const void *vertexUvData;
	uint32_t vertexUvStride;

	uint32_t indexCount;
	const void *indexData;
	IndexFormat::Enum indexFormat;

	// optional. indexCount / 3 in length.
	// Charter also uses material boundaries as a hint to cut charts.
	const uint16_t *faceMaterialData;
};

struct OutputChart
{
	uint32_t *indexArray;
	uint32_t indexCount;
};

struct OutputVertex
{
	float uv[2];
	uint32_t xref;   // Index of input vertex from which this output vertex originated.
};

struct OutputMesh
{
	OutputChart *chartArray;
	uint32_t chartCount;
	uint32_t *indexArray;
	uint32_t indexCount;
	OutputVertex *vertexArray;
	uint32_t vertexCount;
};

void SetPrint(PrintFunc print);
Atlas *Create();
void Destroy(Atlas *atlas);
// useColocalVertices - generates fewer charts (good), but is more sensitive to bad geometry.
AddMeshError AddMesh(Atlas *atlas, const InputMesh &mesh, bool useColocalVertices = true);
void Generate(Atlas *atlas, CharterOptions charterOptions = CharterOptions(), PackerOptions packerOptions = PackerOptions());
uint32_t GetWidth(const Atlas *atlas);
uint32_t GetHeight(const Atlas *atlas);
uint32_t GetNumCharts(const Atlas *atlas);
const OutputMesh * const *GetOutputMeshes(const Atlas *atlas);
const char *StringForEnum(AddMeshErrorCode::Enum error);

} // namespace xatlas

#endif // XATLAS_H