mirror of
https://github.com/Relintai/mesh_utils.git
synced 2024-11-12 10:25:24 +01:00
Added uv_unwrap method to MeshUtils. Also added xatlas from engine/thirdparty to the module under a different namespace. I plan to modify it.
This commit is contained in:
parent
92b6066d02
commit
f5cca2cfb8
1
SCsub
1
SCsub
@ -13,6 +13,7 @@ sources = [
|
|||||||
"mesh_utils.cpp",
|
"mesh_utils.cpp",
|
||||||
"mesh_merger.cpp",
|
"mesh_merger.cpp",
|
||||||
"fast_quadratic_mesh_simplifier.cpp",
|
"fast_quadratic_mesh_simplifier.cpp",
|
||||||
|
"xatlas/xatlas.cpp",
|
||||||
]
|
]
|
||||||
|
|
||||||
if ARGUMENTS.get('custom_modules_shared', 'no') == 'yes':
|
if ARGUMENTS.get('custom_modules_shared', 'no') == 'yes':
|
||||||
|
@ -21,9 +21,12 @@ SOFTWARE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "mesh_utils.h"
|
#include "mesh_utils.h"
|
||||||
|
#include "core/variant.h"
|
||||||
|
|
||||||
#include visual_server_h
|
#include visual_server_h
|
||||||
|
|
||||||
|
#include "xatlas/xatlas.h"
|
||||||
|
|
||||||
#if GODOT4
|
#if GODOT4
|
||||||
#define Texture Texture2D
|
#define Texture Texture2D
|
||||||
#endif
|
#endif
|
||||||
@ -459,6 +462,14 @@ Array MeshUtils::remove_doubles_interpolate_normals(Array arr) const {
|
|||||||
return retarr;
|
return retarr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PoolVector2Array MeshUtils::uv_unwrap(Array arr) const {
|
||||||
|
xatlas_mu::Atlas * a = xatlas_mu::Create();
|
||||||
|
|
||||||
|
xatlas_mu::Destroy(a);
|
||||||
|
|
||||||
|
return PoolVector2Array();
|
||||||
|
}
|
||||||
|
|
||||||
MeshUtils::MeshUtils() {
|
MeshUtils::MeshUtils() {
|
||||||
_instance = this;
|
_instance = this;
|
||||||
}
|
}
|
||||||
@ -473,6 +484,8 @@ void MeshUtils::_bind_methods() {
|
|||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("remove_doubles", "arr"), &MeshUtils::remove_doubles);
|
ClassDB::bind_method(D_METHOD("remove_doubles", "arr"), &MeshUtils::remove_doubles);
|
||||||
ClassDB::bind_method(D_METHOD("remove_doubles_interpolate_normals", "arr"), &MeshUtils::remove_doubles_interpolate_normals);
|
ClassDB::bind_method(D_METHOD("remove_doubles_interpolate_normals", "arr"), &MeshUtils::remove_doubles_interpolate_normals);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("uv_unwrap", "arr"), &MeshUtils::uv_unwrap);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GODOT4
|
#if GODOT4
|
||||||
|
@ -23,6 +23,7 @@ SOFTWARE.
|
|||||||
#ifndef MESH_UTILS_H
|
#ifndef MESH_UTILS_H
|
||||||
#define MESH_UTILS_H
|
#define MESH_UTILS_H
|
||||||
|
|
||||||
|
#include "core/variant.h"
|
||||||
#include "core/version.h"
|
#include "core/version.h"
|
||||||
|
|
||||||
#if VERSION_MAJOR > 3
|
#if VERSION_MAJOR > 3
|
||||||
@ -52,6 +53,9 @@ public:
|
|||||||
//Normals are always interpolated, merged
|
//Normals are always interpolated, merged
|
||||||
Array remove_doubles_interpolate_normals(Array arr) const;
|
Array remove_doubles_interpolate_normals(Array arr) const;
|
||||||
|
|
||||||
|
//Only unwraps, does not create new seams
|
||||||
|
PoolVector2Array uv_unwrap(Array arr) const;
|
||||||
|
|
||||||
MeshUtils();
|
MeshUtils();
|
||||||
~MeshUtils();
|
~MeshUtils();
|
||||||
|
|
||||||
|
21
xatlas/LICENSE
Normal file
21
xatlas/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
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.
|
9609
xatlas/xatlas.cpp
Normal file
9609
xatlas/xatlas.cpp
Normal file
File diff suppressed because it is too large
Load Diff
260
xatlas/xatlas.h
Normal file
260
xatlas/xatlas.h
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
/*
|
||||||
|
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>
|
||||||
|
*/
|
||||||
|
|
||||||
|
//This is a modified version of godot's xatlas library!
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef XATLAS_MU_H
|
||||||
|
#define XATLAS_MU_H
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace xatlas_mu {
|
||||||
|
|
||||||
|
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
|
Loading…
Reference in New Issue
Block a user