jpcy / xatlas Goto Github PK
View Code? Open in Web Editor NEWMesh parameterization / UV unwrapping library
License: MIT License
Mesh parameterization / UV unwrapping library
License: MIT License
Did a quick scan for the latest master (ccf567a) with PVS Studio:
In attachment you can found a full scan log in HTML format. Hope that it's not a lot of false-positive alarms :)
Thanks!
fullhtml.zip
See godotengine/godot#30129 and build log on AppVeyor CI using Visual Studio 2015: https://ci.appveyor.com/project/akien-mga/godot/builds/25592281
Apparently the library builds fine against VS 2017. CC @fire.
Given Godot's big userbase we try to support VS 2015 as min version, even though 2017 or later is recommended (or even MinGW with latest GCC and LTO for best performance). So if xatlas can be made to build against VS 2015 without too much hassle, that would be great for our use case :)
The current duplication removal only handles reused material indexes in the same mesh, is it possible to extend this for multiple meshes when merging and repacking textures?
I think I am honestly not very interested in knowing which vertex or face failed and why. Most users just download models from the web and try them out, and I think they should work anyway.
Simply drop the faces that are broken and bake without them, or pack them as separate charts or whatever. At this point, the original thekla did a better job by continuing ( I can unwrap original Sponza fine with thekla, but not with xatlas).
Godot use xatlas from commit b4b5426
I compiled Godot from https://github.com/qarmin/godot/tree/bb with ubsan sanitizer support scons p=x11 -j6 use_ubsan=yes
(GCC 9 or CLANG 9 and up)
When I imported tps demo(https://github.com/godotengine/tps-demo)
I got this ubsan errors
thirdparty/xatlas/xatlas.cpp:6537:9: runtime error: null pointer passed as argument 1, which is declared to never be null
thirdparty/xatlas/xatlas.cpp:6537:9: runtime error: null pointer passed as argument 2, which is declared to never be null
thirdparty/xatlas/xatlas.cpp:6540:9: runtime error: null pointer passed as argument 1, which is declared to never be null
thirdparty/xatlas/xatlas.cpp:6540:9: runtime error: null pointer passed as argument 2, which is declared to never be null
thirdparty/xatlas/xatlas.cpp:7110:38: runtime error: division by zero
thirdparty/xatlas/xatlas.cpp:3944:19: runtime error: division by zero
thirdparty/xatlas/xatlas.cpp:3947:19: runtime error: division by zero
thirdparty/xatlas/xatlas.cpp:3950:19: runtime error: division by zero
thirdparty/xatlas/xatlas.cpp:3844:28: runtime error: division by zero
and leaks described in godotengine/godot#31488 (but this is another issue)
Hi,
I am trying to unwrap a mesh and I expect it to split into multiple meshes with one texture each with limited resolution.
I set the PackOptions::resolution to the maximum resolution (number of pixels on one side) of the texture, eg. 512, and I set the PackOptions::texelsPerUnit to the ratio of model distance to texel width, eg. 0.1 (that is 10 pixels per 1 unit distance).
I get just one mesh (altough with multiple charts), but the uv coordinates are totally weird. The uv coordinates are in range like 35 to 45. And the charts are next to each other instead of overlapping in the same texture space.
The Atlas::with and height is at the value that I set in the resolution most of the time, but I also noticed that sometimes they are few pixels larger.
I have also noticed PackOptions::maxChartSize now, is that related to my problem? I do not understand what units does it limit. Is it pixels or number of charts or something else?
Thanks for any help and explanation.
xatlas.cpp
is missing a #include <limits.h>
on some compilers where it isn't included by the other headers, compilation fails:
../../../3rdparty/xatlas/xatlas.cpp: At global scope:
../../../3rdparty/xatlas/xatlas.cpp:4820:32: error: ‘UINT_MAX’ was not declared in this scope
PriorityQueue(uint32_t size = UINT_MAX) : maxSize(size) {}
I know that you (jpcy) warned me about repack duplicating the same textures multiple times. I tried using the example with bigger models, and the resultant texture atlases were immensely bigger in size than original.
Is it very difficult to use material ids to avoid duplication of the same texture? Duplicating the same texture 2-3 times is fine, but duplicating it like 20 times is a problem. I really wasn't expecting this. 😥
Just use example_repack for this model, and then check the texture size (56 megabytes), while the sum of original file sizes is less then 200 KB:
cj_bag_reclaim.zip
I'm generating atlases for at least 4000 models and now, imagine having 50mb+ textures per model.
If this is very difficult to implement, then please add me on discord (saml1er#8752), I can offer something in return if you can resolve this.
The commit that introduced Array<T>
(fb20efd) broke the build for compilers that strictly parse templates (gcc, clang...).
The find
and replaceWithLast
functions use undefined functions nv::find
and nv::swap
.
The latter can just be replaced with std::swap
, and the first, I don't know. These Array
functions are dead code anyway so they could be removed altogether.
Giving it a try with Godot, maybe I missed something, but it crashes on exit with following backtrace:
#0 0x00007ffff50c5cc1 in _int_free (have_lock=0, p=<optimized out>,
av=0x7ffff5419c40 <main_arena>) at malloc.c:4295
#1 __GI___libc_free (mem=0x555560bdccf0) at malloc.c:3124
#2 0x00005555569144ee in __gnu_cxx::new_allocator<unsigned int>::deallocate (
this=0x555560c05738, __p=0x555560bdccf0)
at /usr/include/c++/7/ext/new_allocator.h:125
#3 0x000055555690ea1e in std::allocator_traits<std::allocator<unsigned int> >::deallocate (__a=..., __p=0x555560bdccf0, __n=64)
at /usr/include/c++/7/bits/alloc_traits.h:462
#4 0x000055555690660c in std::_Vector_base<unsigned int, std::allocator<unsigned int> >::_M_deallocate (this=0x555560c05738, __p=0x555560bdccf0, __n=64)
at /usr/include/c++/7/bits/stl_vector.h:180
#5 0x00005555569058d9 in std::_Vector_base<unsigned int, std::allocator<unsigned int> >::~_Vector_base (this=0x555560c05738, __in_chrg=<optimized out>)
at /usr/include/c++/7/bits/stl_vector.h:162
#6 0x0000555556901165 in std::vector<unsigned int, std::allocator<unsigned int> >::~vector (this=0x555560c05738, __in_chrg=<optimized out>)
at /usr/include/c++/7/bits/stl_vector.h:435
#7 0x00005555568fba4c in xatlas::internal::param::Chart::~Chart (
this=0x555560c056e0, __in_chrg=<optimized out>)
at thirdparty/xatlas/xatlas.cpp:5260
#8 0x00005555568fbae7 in xatlas::internal::param::MeshCharts::~MeshCharts (
this=0x555560a14280, __in_chrg=<optimized out>)
---Type <return> to continue, or q <return> to quit---
at thirdparty/xatlas/xatlas.cpp:5926
#9 0x00005555568fc999 in xatlas::internal::param::Atlas::~Atlas (
this=0x555560999810, __in_chrg=<optimized out>)
at thirdparty/xatlas/xatlas.cpp:6230
#10 0x000055555690103e in xatlas::Atlas::~Atlas (this=0x555560999810,
__in_chrg=<optimized out>) at thirdparty/xatlas/xatlas.cpp:7032
#11 0x00005555568e6cf9 in xatlas::Destroy (atlas=0x555560999810)
at thirdparty/xatlas/xatlas.cpp:7064
Hi,
When providing inputs to xatlas, should the meshDecl.indexData always be populated with triangles only?
Can I provide polygons?
There are some compiler warnings related to the use of the macro XA_NEW when using gcc and -std=c++11:
src/ext/xatlas.cpp:5072:65: warning: ISO C++11 requires at least one argument for the "..." in a variadic macro
ChartBuildData *chart = XA_NEW(MemTag::Default, ChartBuildData);
...
A simple solution is to use two versions of this macro, one with and one without variable arguments:
#define XA_NEW(tag, type) new (XA_ALLOC(tag, type)) type()
#define XA_NEW_ARGS(tag, type, ...) new (XA_ALLOC(tag, type)) type(__VA_ARGS__)
#define XA_FREE(ptr) internal::Realloc(ptr, 0, internal::MemTag::Default, __FILE__, __LINE__)
Not all C implementations treat realloc size 0 as free, realloc with size 0 reports as a leak on some Unix operating systems, simply changing realloc 0 to free
reports no leaks
Excellent work on xatlas by the way!
Hi,
I think the kImageChartIndexMask should be 0x1FFFFFFF, not 0x3FFFFFFF.
It is used to mask an index into the Mesh::chartArray, right? In that case it should not overlap with the padding bit.
Thanks
Great project! However, even on small meshes, it generates way too many charts, most of which are very small. Is there a way to control this or it is an intrinsic issue of the algorithm?
Maybe that's an expected behavior for file with such dimensions?
Computing charts
0 charts
Parameterizing charts
0 planar charts, 0 ortho charts, 0 LSCM charts, 0 piecewise charts
Packing 0 charts
Building output meshes
mesh 0: 8457 vertices, 2819 triangles, 0 charts
Here's an example of the algorithm https://shaderbits.com/blog/uv-dilation.
When meshes are merged it causes gaps to appear between charts.
Hi,
I use xatlas to unwrap and split a large mesh into multiple smaller meshes with textures that fulfill opengl limitations on resolution.
Is it also possible to configure the packing algorithm to pack charts that are close to each other in model space to be in same atlas?
This would allow to use frustum culling to skip rendering of some meshes. It may also improve texture cache utilization in gpu.
Thanks
If you could consider it, and now that visual studio also support it since VS2017, it would be really useful to make sure diff/PR/etc are not more painful than it should ?
Hello:
I have a question.when I generate the chart,I find the number of some chart is too small,Wheher I can set the number of chart?
looking forward your reply!
good luck!
<jpcy> Multithreaded tasks aren't very finely grained at this point. A single mesh where all faces are connected will only use one core. I should be able to improve that soon, but I need to swap out the current task scheduler with one that can create sub tasks from any thread first.
Make xatlas use the full power of the computer.
I assume there's no handling of floats in textures. This is the input of HDR formats like HDR and openexr. Is that true?
Other than that, does seem more stable.
On the current master (3401183) I seem to have problems when unwrapping a certain model. It triggers Array's XA_DEBUG_ASSERT(index < m_base.size);
assertion during the convex hull calculation while adding charts, but it seems the actual cause could be nans getting in during the LSCM in the parametrization step (or something else, at least that's how far I was able to track down the issue).
The only options I changed from the default options were setting bilinear to false, setting resolution to 1024, padding to 2 and max chart size to 1024. This is how my settings look in the viewer:
I have also attached the model here:
nan_error.zip
Since the introduction of the simpler roundness metric (551e2e7), I seem to have a problem with a decrease in utilization in a large amount of models. An extreme example would be this cylinder model, which goes from 77% when reverting the commit on the current master (bf395a4) to 22% with the commit included:
curvature_issue_example.zip.
I have tried to combat this by using parameters, but thus far have been unable to "revert" the change introduced by the new roundness metric for a general purpose case with either the roundness weight or the straightness weight. I hoped that maybe you could offer insight into what these changes mean and what I could do to adapt my unwrapping in order to regain some utilization.
xatlas::PackCharts crashes when the resolution is set to something specific. At times, the crash doesn't happen at all. You can use this model to reproduce the crash: clump_output.zip
It is easier to reproduce the crash if you compile it in debug mode. The crash can happen anywhere.
ASSERT: texcoord.x >= 0 && texcoord.y >= 0 C:\Users\danish\Documents\Git\Github\Repositories\saml1er\xatlas\xatlas.cpp 7268
XA_DEBUG_ASSERT(chart->allowRotate);
XA_DEBUG_ASSERT(index < m_size);
<---- from Array class
To reproduce:
uint32_t GetBestAtlasMaxResolution(xatlas::Atlas* atlas)
{
uint32_t maxResolution = std::max(atlas->width, atlas->height);
while (maxResolution % 4 != 0)
{
maxResolution++;
}
return maxResolution;
}
xatlas::SetPrint(printf, true);
xatlas::Atlas* atlas = xatlas::Create();
if (!AddMeshesToAtlas(atlas, model, uvs)) { return EXIT_FAILURE; }
xatlas::PackOptions packOptions;
packOptions.createImage = true;
packOptions.padding = 1;
packOptions.texelsPerUnit = 1.0f;
xatlas::PackCharts(atlas, packOptions);
// Get 4x4 resolution for DXT 1
uint32_t bestAtlasReslotution = GetBestAtlasMaxResolution(atlas);
printf("packing charts again with resolution: %d\n", (int)bestAtlasReslotution);
xatlas::Destroy(atlas);
atlas = xatlas::Create();
if (!AddMeshesToAtlas(atlas, model, uvs)) { return EXIT_FAILURE; }
packOptions.resolution = bestAtlasReslotution;
xatlas::PackCharts(atlas, packOptions);
Full code (modified example_repack): https://pastebin.com/mdZq6YH7
I'm working on a project which allows you to generate texture atlases for 3D models (.obj files) in order to reduce the number of images used by the model by copying the pixels from textures to atlas. xatlas is nice, but it will scale the UVs in order to fit multiple charts within one atlas.
How about adding an option to not resize the UVs at all and if the charts don't fit within the resolution of the atlas, then create multiple atlases for the remaining charts if they don't fit in one?
I've tested xatlas with two .obj models (textures included):
models.zip
Cube - A basic cube with 3 textures.
In this case, UVs are scaled up.
Dwarf - model from DirectX samples. I converted it to .obj.
For this model, UVs are scaled down.
If this gets resolved, xatlas will be perfect 💯
Hello:
I have a quzzle.
I have a mesh, and I use your tool 'xalats'computing the chart,but when computed,I found taht the charts is too close,so I want ask you whether I can set the interval between charts,
please give ne some advice.Thank you!
I have built Embree and put the .dll in the same location as the viewer executable but when I try and bake a lightmap in the UI I just get an error saying it cannot load embree3.dll
Any thoughts?
Cheers
Simon
What is MAX_SIZE of xatlas?
I try add my whole scene to xatlas to build Atlas. My scene mesh object count is 222. Is it greater than xatlas size?
my call:
`
xatlas::SetPrint(Print, s_verbose);
m_atlas = xatlas::Create();
// Set progress callback.
Stopwatch stopwatch;
xatlas::SetProgressCallback(m_atlas, ProgressCallback, &stopwatch);
xatlas::MeshDecl meshDecl;
meshDecl.vertexCount = _tran->m_mesh->n_vertices;
meshDecl.vertexPositionData = &position.data()[0].data[0];
meshDecl.vertexPositionStride = sizeof(UVVec3);
meshDecl.indexCount = (uint32_t)indices.size();
meshDecl.indexData = indices.data();
meshDecl.indexFormat = xatlas::IndexFormat::UInt32;
xatlas::AddMeshError::Enum error = xatlas::AddMesh(m_atlas, meshDecl);
if (error != xatlas::AddMeshError::Success)
{
xatlas::Destroy(m_atlas);
printf("\rError adding mesh %s \n", xatlas::StringForEnum(error));
return;
}
xatlas::AddMeshJoin(m_atlas);
xatlas::Generate(m_atlas);
`
I would like the option to keep the input and output meshes without changes (without adding new vertices to the new mesh), so the generated uvs can be drawn directly using a second stream without having to edit the original data. This is useful if you want to use a single model with various instances.
The way I was thinking to achieve this is to "preprocess" the original mesh by generating a dummy lightmap of the single mesh and use the generated mesh for the second lightmap generation that includes other meshes in the scene.
Tried setting ChartOptions growFaceCount to 0 but no luck, it crashes.
Tried setting setting ChartOptions maxThreshold to 0 on the first pass and a large number on the second, and the vertex keeps constant, however the lightmap for a single cube is not generated correctly (it is correct when not setting maxThreshold on the second pass).
Also I see that the number of vertexes increases too much with maxThreshold =0.
Any ideas would be appreciated
Furthermore, the option for keeping each mesh on a single lightmap would be desirable insead of splitting it on various lightmaps
Thanks!
xatlas asserts with line 6927 XA_DEBUG_ASSERT(texcoord.x >= 0 && texcoord.y >= 0);
.
I'll try to find some sample data.
Line 1 in 4cf7f14
Since this is not part of my lightmapper example, you could remove the first line of the obj file, because that was a comment about the corresponding example lightmap size :)
Cool project!
I got an already segmented / already parameterized mesh. Now I would like to use the packer with this existing segmentation and parameterization.
MeshDecl has vertexUvData and vertexUvStride, but it seems they are ignored when I'm calling xatlas::Generate(). I also tryed calling xatlas::PackCharts, but it fails with the message "ComputeCharts should be called first".
While the last freezing model was an error on my part, I believe I have now found a model that actually freezes during the chart packing step (default parameters in viewer, version is current master 1d8f612). It gets stuck inside drawAA due to NaNs under Release, and under Debug, it fails an assert when trying to add a zero-area face to a chart. I was under the impression zero-area and degenerate faces were ignored, so I'm not sure how it even manages to get there, that might be the core of the issue.
I have a mesh of 1000K faces, it spend about 12 hours to generate the atlas. so it would be much better if you can sped up this ^ ^.
Original thekla_atlas has MIT license, which is an excellent choice. Would you please specify license for this fork? We cannot actually use it without it. Thanks
Hi,
xatlas is a great library. Thanks a lot.
I have a question.
In my model, a mesh can have more than one material. Different material can be applied to each triangles. How should I handle this case?
Thanks in advance
Caused by dc04de3. Use this to reproduce: lodferryland.zip
example_repack.exe clump_output.obj
Line 7102 in 93cf61d
I'm getting asserts where the value is close to one of the other value but slightly over:
Tried doing this, but do you have an approximately equals function that is scaled by the values?
XA_DEBUG_ASSERT(unsigned int(extents.x) <= realMaxChartSize && unsigned int(extents.y) <= realMaxChartSize);
Edited:
Trialing:
XA_DEBUG_ASSERT(!(extents.x > realMaxChartSize && extents.x - realMaxChartSize > FLT_EPSILON || extents.y > realMaxChartSize && extents.y - realMaxChartSize > FLT_EPSILON));
This doesn't work.
When combining texture charts values, does xatlas handle alphas in the 4th channel?
Here is a model consisting of 5 triangles: https://drive.google.com/open?id=1dwuUdRA3TPoXaiiO7zZi8r08U2R6IqFy
Somehow feeding it to xatlas causes a crash. I managed to narrow the problem down to createFaceGroups() call, but it's hard to dig up deeper without knowing what the code actually does.
(Perhaps it should be (also?) posted to original thekla_atlas github?)
Hello!
Here is the original OBJ file: https://we.tl/t-g6LNxfOi8o (35 MB ZIP, 200 MB OBJ, 1M tris).
On some surfaces weird-looking charts are being generated:
I'm using viewer with default settings (via Generate button). I've tried to adjust some of the parameters, but it will anyway appear on the different surfaces.
Is there any way to improve charts generation? Box projection mapping?
Thanks!
I seem to have an issue with xatlas freezing during unwrap on the current master (4484035) with the default values in the viewer.
I have attached the model, the only special thing about it I noticed is that it is rather large.
freezing_model.zip
The UV provided in the output seem to be relative the bottom-left corner and not top-left, am I correct ?
It would be nice to mention this somewhere explicitly ! Just to avoid some head-scratching
For some meshes, the vertexCount is less than the actual vertex count (meshDecl.vertexCount)
For example, I have a mesh with 92 vertices. but in the atlas output, the vertex count is 90.
I am updating the UVs of original mesh with the atlas UVs using xref.
Now for the missing vertices, I dont have UVs.
How to handle this case?
Should I re-write the original mesh?
Hello
When I use the xatlas to compute my mesh,I find something wrong.Firstly, my mesh is oblique photogrammetry model, so the mesh is not close.I found that in the console show that :(1)failed to closed holes;(2)doesn't have disk topology;(3)invalid parameterization, self-intersecting boundary;(4)invalid parameterization, 2 / 78 flipped triangles.I am confused.because of aboved ,there are many charts with invalid parameterizations.
So I want ask:(1)whether the mesh must close? (2) is the xatlas tool can handle the flip triamgle?
looking forward to you reply? thank you again.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.