123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- /*
- MIT License
- Copyright (c) 2018-2020 Jonathan Young
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
- */
- /*
- thekla_atlas
- MIT License
- https://github.com/Thekla/thekla_atlas
- Copyright (c) 2013 Thekla, Inc
- Copyright NVIDIA Corporation 2006 -- Ignacio Castano <icastano@nvidia.com>
- */
- #pragma once
- #ifndef XATLAS_H
- #define XATLAS_H
- #include <stddef.h>
- #include <stdint.h>
- namespace xatlas {
- enum class ChartType {
- Planar,
- Ortho,
- LSCM,
- Piecewise,
- Invalid
- };
- // A group of connected faces, belonging to a single atlas.
- struct Chart {
- uint32_t *faceArray;
- uint32_t atlasIndex; // Sub-atlas index.
- uint32_t faceCount;
- ChartType type;
- uint32_t material;
- };
- // Output vertex.
- struct Vertex {
- 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.
- float uv[2]; // Not normalized - values are in Atlas width and height range.
- uint32_t xref; // Index of input vertex from which this output vertex originated.
- };
- // Output mesh.
- struct Mesh {
- Chart *chartArray;
- uint32_t *indexArray;
- Vertex *vertexArray;
- uint32_t chartCount;
- uint32_t indexCount;
- uint32_t vertexCount;
- };
- static const uint32_t kImageChartIndexMask = 0x1FFFFFFF;
- static const uint32_t kImageHasChartIndexBit = 0x80000000;
- static const uint32_t kImageIsBilinearBit = 0x40000000;
- static const uint32_t kImageIsPaddingBit = 0x20000000;
- // Empty on creation. Populated after charts are packed.
- struct Atlas {
- uint32_t *image;
- 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 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 chartCount; // Total number of charts in all meshes.
- uint32_t meshCount; // Number of output meshes. Equal to the number of times AddMesh was called.
- float texelsPerUnit; // Equal to PackOptions texelsPerUnit if texelsPerUnit > 0, otherwise an estimated value to match PackOptions resolution.
- };
- // Create an empty atlas.
- Atlas *Create();
- void Destroy(Atlas *atlas);
- enum class IndexFormat {
- UInt16,
- UInt32
- };
- // Input mesh declaration.
- struct MeshDecl {
- const void *vertexPositionData = nullptr;
- const void *vertexNormalData = nullptr; // optional
- const void *vertexUvData = nullptr; // optional. The input UVs are provided as a hint to the chart generator.
- const void *indexData = nullptr; // optional
- // 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.
- 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 vertexPositionStride = 0;
- uint32_t vertexNormalStride = 0; // optional
- uint32_t vertexUvStride = 0; // optional
- uint32_t indexCount = 0;
- int32_t indexOffset = 0; // optional. Add this offset to all indices.
- 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.
- float epsilon = 1.192092896e-07F;
- };
- 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.
- AddMeshError AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountHint = 0);
- // Wait for AddMesh async processing to finish. ComputeCharts / Generate call this internally.
- void AddMeshJoin(Atlas *atlas);
- struct UvMeshDecl {
- const void *vertexUvData = nullptr;
- const void *indexData = nullptr; // optional
- 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 vertexStride = 0;
- uint32_t indexCount = 0;
- int32_t indexOffset = 0; // optional. Add this offset to all indices.
- IndexFormat indexFormat = IndexFormat::UInt16;
- };
- 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;
- 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.
- // Weights determine chart growth. Higher weights mean higher cost for that metric.
- float normalDeviationWeight = 2.0f; // Angle between face and average chart normal.
- float roundnessWeight = 0.01f;
- float straightnessWeight = 6.0f;
- float normalSeamWeight = 4.0f; // If > 1000, normal seams are fully respected.
- float textureSeamWeight = 0.5f;
- 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.
- 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.
- void ComputeCharts(Atlas *atlas, ChartOptions options = ChartOptions());
- struct PackOptions {
- // 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;
- // 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;
- // Leave space around charts for texels that would be sampled by bilinear filtering.
- bool bilinear = true;
- // Align charts to 4x4 blocks. Also improves packing speed, since there are fewer possible chart locations to consider.
- bool blockAlign = false;
- // Slower, but gives the best result. If false, use random chart placement.
- bool bruteForce = false;
- // Create Atlas::image
- bool createImage = false;
- // Rotate charts to the axis of their convex hull.
- bool rotateChartsToAxis = true;
- // Rotate charts to improve packing.
- bool rotateCharts = true;
- };
- // Call after ComputeCharts. Can be called multiple times to re-pack charts with different options.
- void PackCharts(Atlas *atlas, 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.
- enum class ProgressCategory {
- AddMesh,
- ComputeCharts,
- PackCharts,
- BuildOutputMeshes
- };
- // May be called from any thread. Return false to cancel.
- typedef bool (*ProgressFunc)(ProgressCategory category, int progress, void *userData);
- void SetProgressCallback(Atlas *atlas, ProgressFunc progressFunc = nullptr, void *progressUserData = nullptr);
- // Custom memory allocation.
- typedef void *(*ReallocFunc)(void *, size_t);
- typedef void (*FreeFunc)(void *);
- void SetAlloc(ReallocFunc reallocFunc, FreeFunc freeFunc = nullptr);
- // Custom print function.
- typedef int (*PrintFunc)(const char *, ...);
- void SetPrint(PrintFunc print, bool verbose);
- // Helper functions for error messages.
- const char *StringForEnum(AddMeshError error);
- const char *StringForEnum(ProgressCategory category);
- } // namespace xatlas
- #endif // XATLAS_H
|