| 1 | /* |
| 2 | MIT License |
| 3 | |
| 4 | Copyright (c) 2018-2020 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 <stddef.h> |
| 35 | #include <stdint.h> |
| 36 | |
| 37 | namespace xatlas { |
| 38 | |
| 39 | enum 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. |
| 49 | struct 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. |
| 59 | struct 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. |
| 68 | struct 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 | |
| 78 | static const uint32_t kImageChartIndexMask = 0x1FFFFFFF; |
| 79 | static const uint32_t kImageHasChartIndexBit = 0x80000000; |
| 80 | static const uint32_t kImageIsBilinearBit = 0x40000000; |
| 81 | static const uint32_t kImageIsPaddingBit = 0x20000000; |
| 82 | |
| 83 | // Empty on creation. Populated after charts are packed. |
| 84 | struct 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. |
| 98 | Atlas *Create(); |
| 99 | |
| 100 | void Destroy(Atlas *atlas); |
| 101 | |
| 102 | enum class IndexFormat |
| 103 | { |
| 104 | UInt16, |
| 105 | UInt32 |
| 106 | }; |
| 107 | |
| 108 | // Input mesh declaration. |
| 109 | struct 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 | |
| 141 | enum 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. |
| 151 | AddMeshError AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint = 0); |
| 152 | |
| 153 | // Wait for AddMesh async processing to finish. ComputeCharts / Generate call this internally. |
| 154 | void AddMeshJoin(Atlas *atlas); |
| 155 | |
| 156 | struct 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 | |
| 168 | AddMeshError AddUvMesh(Atlas *atlas, const UvMeshDecl &decl); |
| 169 | |
| 170 | // Custom parameterization function. texcoords initial values are an orthogonal parameterization. |
| 171 | typedef void (*ParameterizeFunc)(const float *positions, float *texcoords, uint32_t vertexCount, const uint32_t *indices, uint32_t indexCount); |
| 172 | |
| 173 | struct 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. |
| 195 | void ComputeCharts(Atlas *atlas, ChartOptions options = ChartOptions()); |
| 196 | |
| 197 | struct 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. |
| 235 | void 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. |
| 238 | void Generate(Atlas *atlas, ChartOptions chartOptions = ChartOptions(), PackOptions packOptions = PackOptions()); |
| 239 | |
| 240 | // Progress tracking. |
| 241 | enum class ProgressCategory |
| 242 | { |
| 243 | AddMesh, |
| 244 | ComputeCharts, |
| 245 | PackCharts, |
| 246 | BuildOutputMeshes |
| 247 | }; |
| 248 | |
| 249 | // May be called from any thread. Return false to cancel. |
| 250 | typedef bool (*ProgressFunc)(ProgressCategory category, int progress, void *userData); |
| 251 | |
| 252 | void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc = nullptr, void *progressUserData = nullptr); |
| 253 | |
| 254 | // Custom memory allocation. |
| 255 | typedef void *(*ReallocFunc)(void *, size_t); |
| 256 | typedef void (*FreeFunc)(void *); |
| 257 | void SetAlloc(ReallocFunc reallocFunc, FreeFunc freeFunc = nullptr); |
| 258 | |
| 259 | // Custom print function. |
| 260 | typedef int (*PrintFunc)(const char *, ...); |
| 261 | void SetPrint(PrintFunc print, bool verbose); |
| 262 | |
| 263 | // Helper functions for error messages. |
| 264 | const char *StringForEnum(AddMeshError error); |
| 265 | const char *StringForEnum(ProgressCategory category); |
| 266 | |
| 267 | } // namespace xatlas |
| 268 | |
| 269 | #endif // XATLAS_H |
| 270 | |