Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions src/atlas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,66 @@ MeshResult Atlas::getMesh(std::uint32_t index) const
return std::make_tuple(mapping, indices, uvs);
}

VertexAssignment Atlas::getMeshVertexAssignment(std::uint32_t meshIndex) const
{
if (meshIndex >= m_atlas->meshCount)
{
throw std::out_of_range("Mesh index " + std::to_string(meshIndex) + " out of bounds for atlas with " + std::to_string(m_atlas->meshCount) + " meshes.");
}

auto const& mesh = m_atlas->meshes[meshIndex];

py::array_t<std::uint32_t> atlasIndex(py::array::ShapeContainer{mesh.vertexCount});
py::array_t<std::uint32_t> chartIndex(py::array::ShapeContainer{mesh.vertexCount});
auto atlasIndex_ = atlasIndex.mutable_unchecked<1>();
auto chartIndex_ = chartIndex.mutable_unchecked<1>();
for (size_t v = 0; v < static_cast<size_t>(mesh.vertexCount); ++v)
{
auto const& vertex = mesh.vertexArray[v];
atlasIndex_(v) = vertex.atlasIndex;
chartIndex_(v) = vertex.chartIndex;
}

return std::make_tuple(atlasIndex, chartIndex);
}

uint32_t Atlas::getMeshChartCount(std::uint32_t meshIndex) const
{
if (meshIndex >= m_atlas->meshCount)
throw std::out_of_range("Mesh index " + std::to_string(meshIndex) + " out of bounds for atlas with " + std::to_string(m_atlas->meshCount) + " meshes.");

auto const& mesh = m_atlas->meshes[meshIndex];

return mesh.chartCount;
}

Chart Atlas::getMeshChart(std::uint32_t meshIndex, std::uint32_t chartIndex) const
{
if (meshIndex >= m_atlas->meshCount)
throw std::out_of_range("Mesh index " + std::to_string(meshIndex) + " out of bounds for atlas with " + std::to_string(m_atlas->meshCount) + " meshes.");

auto const& mesh = m_atlas->meshes[meshIndex];

if (chartIndex >= mesh.chartCount)
throw std::out_of_range("Chart index " + std::to_string(chartIndex) + " out of bounds for mesh with " + std::to_string(mesh.chartCount) + " charts.");

xatlas::Chart& chart = mesh.chartArray[chartIndex];
py::array_t<std::uint32_t> faces(py::array::ShapeContainer{chart.faceCount});
auto faces_ = faces.mutable_unchecked<1>();
for (size_t i = 0; i < static_cast<size_t>(chart.faceCount); ++i)
{
faces_(i) = chart.faceArray[i];
}

Chart chart_;
chart_.faces = faces;
chart_.atlasIndex = chart.atlasIndex;
chart_.type = chart.type;
chart_.material = chart.material;

return chart_;
}

float Atlas::getUtilization(std::uint32_t index) const
{
if (index >= m_atlas->atlasCount)
Expand Down Expand Up @@ -259,12 +319,21 @@ py::array_t<std::uint8_t> Atlas::getChartImage(std::uint32_t index) const

void Atlas::bind(py::module& m)
{
py::class_<Chart>(m, "Chart")
.def_property_readonly("faces", [](Chart const& self) { return self.faces; })
.def_property_readonly("atlas_index", [](Chart const& self) { return self.atlasIndex; })
.def_property_readonly("type", [](Chart const& self) { return self.type; })
.def_property_readonly("material", [](Chart const& self) { return self.material; });

py::class_<Atlas>(m, "Atlas")
.def(py::init<>())
.def("add_mesh", &Atlas::addMesh, py::arg("positions"), py::arg("indices"), py::arg("normals") = std::nullopt, py::arg("uvs") = std::nullopt)
.def("add_uv_mesh", &Atlas::addUvMesh, py::arg("uvs"), py::arg("indices"), py::arg("face_materials") = std::nullopt)
.def("generate", &Atlas::generate, py::arg("chart_options") = xatlas::ChartOptions(), py::arg("pack_options") = xatlas::PackOptions(), py::arg("verbose") = false)
.def("get_mesh", &Atlas::getMesh, py::arg("mesh_index"))
.def("get_mesh_vertex_assignment", &Atlas::getMeshVertexAssignment, py::arg("mesh_index"))
.def("get_mesh_chart_count", &Atlas::getMeshChartCount, py::arg("mesh_index"))
.def("get_mesh_chart", &Atlas::getMeshChart, py::arg("mesh_index"), py::arg("chart_index"))
.def("get_utilization", &Atlas::getUtilization, py::arg("atlas_index"))
.def("get_chart_image", &Atlas::getChartImage, py::arg("atlas_index"))
.def_property_readonly("atlas_count", [](Atlas const& self) { return self.m_atlas->atlasCount; })
Expand Down
25 changes: 24 additions & 1 deletion src/atlas.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,24 @@
#include <optional>
#include <tuple>

using MeshResult = std::tuple<pybind11::array_t<std::uint32_t>, pybind11::array_t<std::uint32_t>, pybind11::array_t<float>>;
using MeshResult = std::tuple<
pybind11::array_t<std::uint32_t>,
pybind11::array_t<std::uint32_t>,
pybind11::array_t<float>
>;

using VertexAssignment = std::tuple<
pybind11::array_t<std::uint32_t>, // Atlas index
pybind11::array_t<std::uint32_t> // Chart index
>;

struct Chart
{
pybind11::array_t<std::uint32_t> faces;
uint32_t atlasIndex; // Sub-atlas index.
xatlas::ChartType type;
uint32_t material;
};

class Atlas
{
Expand All @@ -56,6 +73,12 @@ class Atlas

MeshResult getMesh(std::uint32_t index) const;

VertexAssignment getMeshVertexAssignment(std::uint32_t meshIndex) const;

uint32_t getMeshChartCount(std::uint32_t meshIndex) const;

Chart getMeshChart(std::uint32_t meshIndex, std::uint32_t chartIndex) const;

float getUtilization(std::uint32_t index) const;

pybind11::array_t<std::uint8_t> getChartImage(std::uint32_t index) const;
Expand Down
8 changes: 7 additions & 1 deletion src/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,13 @@ void exportObj(std::string const& path,

PYBIND11_MODULE(xatlas, m)
{
// Bindings
py::enum_<xatlas::ChartType>(m, "ChartType")
.value("Planar", xatlas::ChartType::Planar)
.value("Ortho", xatlas::ChartType::Ortho)
.value("LSCM", xatlas::ChartType::LSCM)
.value("Piecewise", xatlas::ChartType::Piecewise)
.value("Invalid", xatlas::ChartType::Invalid);

ChartOptions::bind(m);
PackOptions::bind(m);
Atlas::bind(m);
Expand Down
Loading