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