1 /*
2 MIT License
3 
4 Copyright (c) 2018-2019 Jonathan Young
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 /*
25 thekla_atlas
26 MIT License
27 https://github.com/Thekla/thekla_atlas
28 Copyright (c) 2013 Thekla, Inc
29 Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
30 */
31 #pragma once
32 #ifndef XATLAS_H
33 #define XATLAS_H
34 #include <stdint.h>
35 
36 namespace xatlas {
37 
38 struct ChartType
39 {
40 	enum Enum
41 	{
42 		Planar,
43 		Ortho,
44 		LSCM,
45 		Piecewise
46 	};
47 };
48 
49 // A group of connected faces, belonging to a single atlas.
50 struct Chart
51 {
52 	uint32_t atlasIndex; // Sub-atlas index.
53 	uint32_t *faceArray;
54 	uint32_t faceCount;
55 	uint32_t material;
56 	ChartType::Enum type;
57 };
58 
59 // Output vertex.
60 struct Vertex
61 {
62 	int32_t atlasIndex; // Sub-atlas index. -1 if the vertex doesn't exist in any atlas.
63 	int32_t chartIndex; // -1 if the vertex doesn't exist in any chart.
64 	float uv[2]; // Not normalized - values are in Atlas width and height range.
65 	uint32_t xref; // Index of input vertex from which this output vertex originated.
66 };
67 
68 // Output mesh.
69 struct Mesh
70 {
71 	Chart *chartArray;
72 	uint32_t chartCount;
73 	uint32_t *indexArray;
74 	uint32_t indexCount;
75 	Vertex *vertexArray;
76 	uint32_t vertexCount;
77 };
78 
79 static const uint32_t kImageChartIndexMask = 0x1FFFFFFF;
80 static const uint32_t kImageHasChartIndexBit = 0x80000000;
81 static const uint32_t kImageIsBilinearBit = 0x40000000;
82 static const uint32_t kImageIsPaddingBit = 0x20000000;
83 
84 // Empty on creation. Populated after charts are packed.
85 struct Atlas
86 {
87 	uint32_t width; // Atlas width in texels.
88 	uint32_t height; // Atlas height in texels.
89 	uint32_t atlasCount; // Number of sub-atlases. Equal to 0 unless PackOptions resolution is changed from default (0).
90 	uint32_t chartCount; // Total number of charts in all meshes.
91 	uint32_t meshCount; // Number of output meshes. Equal to the number of times AddMesh was called.
92 	Mesh *meshes; // The output meshes, corresponding to each AddMesh call.
93 	float *utilization; // Normalized atlas texel utilization array. E.g. a value of 0.8 means 20% empty space. atlasCount in length.
94 	float texelsPerUnit; // Equal to PackOptions texelsPerUnit if texelsPerUnit > 0, otherwise an estimated value to match PackOptions resolution.
95 	uint32_t *image;
96 };
97 
98 // Create an empty atlas.
99 Atlas *Create();
100 
101 void Destroy(Atlas *atlas);
102 
103 struct IndexFormat
104 {
105 	enum Enum
106 	{
107 		UInt16,
108 		UInt32
109 	};
110 };
111 
112 // Input mesh declaration.
113 struct MeshDecl
114 {
115 	uint32_t vertexCount = 0;
116 	const void *vertexPositionData = nullptr;
117 	uint32_t vertexPositionStride = 0;
118 	const void *vertexNormalData = nullptr; // optional
119 	uint32_t vertexNormalStride = 0; // optional
120 	const void *vertexUvData = nullptr; // optional. The input UVs are provided as a hint to the chart generator.
121 	uint32_t vertexUvStride = 0; // optional
122 	uint32_t indexCount = 0;
123 	const void *indexData = nullptr; // optional
124 	int32_t indexOffset = 0; // optional. Add this offset to all indices.
125 	IndexFormat::Enum indexFormat = IndexFormat::UInt16;
126 
127 	// Optional. indexCount / 3 (triangle count) in length.
128 	// 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.
129 	const bool *faceIgnoreData = nullptr;
130 
131 	// Vertex positions within epsilon distance of each other are considered colocal.
132 	float epsilon = 1.192092896e-07F;
133 };
134 
135 struct AddMeshError
136 {
137 	enum Enum
138 	{
139 		Success, // No error.
140 		Error, // Unspecified error.
141 		IndexOutOfRange, // An index is >= MeshDecl vertexCount.
142 		InvalidIndexCount // Not evenly divisible by 3 - expecting triangles.
143 	};
144 };
145 
146 // Add a mesh to the atlas. MeshDecl data is copied, so it can be freed after AddMesh returns.
147 AddMeshError::Enum AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint = 0);
148 
149 // Wait for AddMesh async processing to finish. ComputeCharts / Generate call this internally.
150 void AddMeshJoin(Atlas *atlas);
151 
152 struct UvMeshDecl
153 {
154 	uint32_t vertexCount = 0;
155 	uint32_t vertexStride = 0;
156 	const void *vertexUvData = nullptr;
157 	uint32_t indexCount = 0;
158 	const void *indexData = nullptr; // optional
159 	int32_t indexOffset = 0; // optional. Add this offset to all indices.
160 	IndexFormat::Enum indexFormat = IndexFormat::UInt16;
161 	const uint32_t *faceMaterialData = nullptr; // Optional. Faces with different materials won't be assigned to the same chart. Must be indexCount / 3 in length.
162 	bool rotateCharts = true;
163 };
164 
165 AddMeshError::Enum AddUvMesh(Atlas *atlas, const UvMeshDecl &decl);
166 
167 struct ChartOptions
168 {
169 	float maxChartArea = 0.0f; // Don't grow charts to be larger than this. 0 means no limit.
170 	float maxBoundaryLength = 0.0f; // Don't grow charts to have a longer boundary than this. 0 means no limit.
171 
172 	// Weights determine chart growth. Higher weights mean higher cost for that metric.
173 	float proxyFitMetricWeight = 2.0f; // Angle between face and average chart normal.
174 	float roundnessMetricWeight = 0.01f;
175 	float straightnessMetricWeight = 6.0f;
176 	float normalSeamMetricWeight = 4.0f; // If > 1000, normal seams are fully respected.
177 	float textureSeamMetricWeight = 0.5f;
178 
179 	float maxThreshold = 2.0f; // If total of all metrics * weights > maxThreshold, don't grow chart. Lower values result in more charts.
180 	uint32_t maxIterations = 1; // Number of iterations of the chart growing and seeding phases. Higher values result in better charts.
181 };
182 
183 // Call after all AddMesh calls. Can be called multiple times to recompute charts with different options.
184 void ComputeCharts(Atlas *atlas, ChartOptions chartOptions = ChartOptions());
185 
186 // Custom parameterization function. texcoords initial values are an orthogonal parameterization.
187 typedef void (*ParameterizeFunc)(const float *positions, float *texcoords, uint32_t vertexCount, const uint32_t *indices, uint32_t indexCount);
188 
189 // Call after ComputeCharts. Can be called multiple times to re-parameterize charts with a different ParameterizeFunc.
190 void ParameterizeCharts(Atlas *atlas, ParameterizeFunc func = nullptr);
191 
192 struct PackOptions
193 {
194 	// Leave space around charts for texels that would be sampled by bilinear filtering.
195 	bool bilinear = true;
196 
197 	// Align charts to 4x4 blocks. Also improves packing speed, since there are fewer possible chart locations to consider.
198 	bool blockAlign = false;
199 
200 	// Slower, but gives the best result. If false, use random chart placement.
201 	bool bruteForce = false;
202 
203 	// Create Atlas::image
204 	bool createImage = false;
205 
206 	// Charts larger than this will be scaled down. 0 means no limit.
207 	uint32_t maxChartSize = 0;
208 
209 	// Number of pixels to pad charts with.
210 	uint32_t padding = 0;
211 
212 	// Unit to texel scale. e.g. a 1x1 quad with texelsPerUnit of 32 will take up approximately 32x32 texels in the atlas.
213 	// If 0, an estimated value will be calculated to approximately match the given resolution.
214 	// If resolution is also 0, the estimated value will approximately match a 1024x1024 atlas.
215 	float texelsPerUnit = 0.0f;
216 
217 	// If 0, generate a single atlas with texelsPerUnit determining the final resolution.
218 	// If not 0, and texelsPerUnit is not 0, generate one or more atlases with that exact resolution.
219 	// If not 0, and texelsPerUnit is 0, texelsPerUnit is estimated to approximately match the resolution.
220 	uint32_t resolution = 0;
221 };
222 
223 // Call after ParameterizeCharts. Can be called multiple times to re-pack charts with different options.
224 void PackCharts(Atlas *atlas, PackOptions packOptions = PackOptions());
225 
226 // Equivalent to calling ComputeCharts, ParameterizeCharts and PackCharts in sequence. Can be called multiple times to regenerate with different options.
227 void Generate(Atlas *atlas, ChartOptions chartOptions = ChartOptions(), ParameterizeFunc paramFunc = nullptr, PackOptions packOptions = PackOptions());
228 
229 // Progress tracking.
230 struct ProgressCategory
231 {
232 	enum Enum
233 	{
234 		AddMesh,
235 		ComputeCharts,
236 		ParameterizeCharts,
237 		PackCharts,
238 		BuildOutputMeshes
239 	};
240 };
241 
242 // May be called from any thread. Return false to cancel.
243 typedef bool (*ProgressFunc)(ProgressCategory::Enum category, int progress, void *userData);
244 
245 void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc = nullptr, void *progressUserData = nullptr);
246 
247 // Custom memory allocation.
248 typedef void *(*ReallocFunc)(void *, size_t);
249 typedef void (*FreeFunc)(void *);
250 void SetAlloc(ReallocFunc reallocFunc, FreeFunc freeFunc = nullptr);
251 
252 // Custom print function.
253 typedef int (*PrintFunc)(const char *, ...);
254 void SetPrint(PrintFunc print, bool verbose);
255 
256 // Helper functions for error messages.
257 const char *StringForEnum(AddMeshError::Enum error);
258 const char *StringForEnum(ProgressCategory::Enum category);
259 
260 } // namespace xatlas
261 
262 #endif // XATLAS_H
263