Browse Source

python: expose meshtools.concatenate() as well.

Relies on the new custom Containers::Iterable constructor.
next
Vladimír Vondruš 3 years ago
parent
commit
f30c1c503f
  1. 9
      doc/python/magnum.meshtools.rst
  2. 4
      doc/python/pages/changelog.rst
  3. 32
      src/python/magnum/meshtools.cpp
  4. 26
      src/python/magnum/test/test_meshtools.py

9
doc/python/magnum.meshtools.rst

@ -26,6 +26,15 @@
.. py:function:: magnum.meshtools.compress_indices .. py:function:: magnum.meshtools.compress_indices
:raise AssertionError: If :p:`mesh` is not indexed :raise AssertionError: If :p:`mesh` is not indexed
.. py:function:: magnum.meshtools.concatenate
:raise AssertionError: If :p:`meshes` is empty
:raise AssertionError: If any of the :p:`meshes` is
:ref:`MeshPrimitive.LINE_STRIP`, :ref:`MeshPrimitive.LINE_LOOP`,
:ref:`MeshPrimitive.TRIANGLE_STRIP` or
:ref:`MeshPrimitive.TRIANGLE_FAN`
:raise AssertionError: If all :p:`meshes` don't have the same
:ref:`MeshPrimitive`
.. py:function:: magnum.meshtools.duplicate .. py:function:: magnum.meshtools.duplicate
:raise AssertionError: If :p:`mesh` is not indexed :raise AssertionError: If :p:`mesh` is not indexed

4
doc/python/pages/changelog.rst

@ -102,8 +102,8 @@ Changelog
- Fixed :ref:`platform.sdl2.Application.InputEvent.Modifier` and - Fixed :ref:`platform.sdl2.Application.InputEvent.Modifier` and
:ref:`platform.glfw.Application.InputEvent.Modifier` to behave properly :ref:`platform.glfw.Application.InputEvent.Modifier` to behave properly
as flags and not just as an enum as flags and not just as an enum
- Exposed :ref:`meshtools.compress_indices()`, :ref:`meshtools.duplicate()`, - Exposed :ref:`meshtools.compress_indices()`, :ref:`meshtools.concatenate()`,
:ref:`meshtools.filter_except_attributes()`, :ref:`meshtools.duplicate()`, :ref:`meshtools.filter_except_attributes()`,
:ref:`meshtools.filter_only_attributes()`, :ref:`meshtools.filter_only_attributes()`,
:ref:`meshtools.generate_indices()`, :ref:`meshtools.interleave()`, :ref:`meshtools.generate_indices()`, :ref:`meshtools.interleave()`,
:ref:`meshtools.owned()`, :ref:`meshtools.remove_duplicates()`, :ref:`meshtools.owned()`, :ref:`meshtools.remove_duplicates()`,

32
src/python/magnum/meshtools.cpp

@ -30,6 +30,7 @@
#include <Magnum/GL/Mesh.h> #include <Magnum/GL/Mesh.h>
#include <Magnum/MeshTools/Compile.h> #include <Magnum/MeshTools/Compile.h>
#include <Magnum/MeshTools/CompressIndices.h> #include <Magnum/MeshTools/CompressIndices.h>
#include <Magnum/MeshTools/Concatenate.h>
#include <Magnum/MeshTools/Duplicate.h> #include <Magnum/MeshTools/Duplicate.h>
#include <Magnum/MeshTools/FilterAttributes.h> #include <Magnum/MeshTools/FilterAttributes.h>
#include <Magnum/MeshTools/GenerateIndices.h> #include <Magnum/MeshTools/GenerateIndices.h>
@ -86,6 +87,37 @@ void meshtools(py::module_& m) {
py::kw_only{}, /* new in pybind11 2.6 */ py::kw_only{}, /* new in pybind11 2.6 */
#endif #endif
py::arg("at_least") = MeshIndexType::UnsignedShort) py::arg("at_least") = MeshIndexType::UnsignedShort)
/** @todo ew, expose Iterable directly */
.def("concatenate", [](const std::vector<std::reference_wrapper<Trade::MeshData>>& meshes, MeshTools::InterleaveFlag flags) {
if(meshes.empty()) {
PyErr_SetString(PyExc_AssertionError, "expected at least one mesh");
throw py::error_already_set{};
}
const MeshPrimitive primitive = meshes[0].get().primitive();
for(std::size_t i = 0; i != meshes.size(); ++i) {
const Trade::MeshData& mesh = meshes[i];
if(mesh.primitive() == MeshPrimitive::LineStrip ||
mesh.primitive() == MeshPrimitive::LineLoop ||
mesh.primitive() == MeshPrimitive::TriangleStrip ||
mesh.primitive() == MeshPrimitive::TriangleFan)
{
PyErr_SetString(PyExc_AssertionError, "invalid mesh primitive");
throw py::error_already_set{};
}
if(mesh.primitive() != primitive) {
PyErr_SetString(PyExc_AssertionError, "inconsistent mesh primitive");
throw py::error_already_set{};
}
}
/** @todo check that the indices/Vertices aren't impl-specific once
it's possible to test */
/** @todo there's a lot more assertions re attribute formats, array
sizes, etc */
return MeshTools::concatenate(Containers::Iterable<const Trade::MeshData>{meshes.data(), meshes.size(), sizeof(std::reference_wrapper<Trade::MeshData>), [](const void* data) -> const Trade::MeshData& {
return static_cast<const std::reference_wrapper<Trade::MeshData>*>(data)->get();
}}, flags);
}, "Concatenate meshes together", py::arg("meshes"), py::arg("flags") = MeshTools::InterleaveFlag::PreserveInterleavedAttributes)
.def("duplicate", [](const Trade::MeshData& mesh) { .def("duplicate", [](const Trade::MeshData& mesh) {
if(!mesh.isIndexed()) { if(!mesh.isIndexed()) {
PyErr_SetString(PyExc_AssertionError, "the mesh is not indexed"); PyErr_SetString(PyExc_AssertionError, "the mesh is not indexed");

26
src/python/magnum/test/test_meshtools.py

@ -45,6 +45,32 @@ class CompressIndices(unittest.TestCase):
with self.assertRaisesRegex(AssertionError, "the mesh is not indexed"): with self.assertRaisesRegex(AssertionError, "the mesh is not indexed"):
meshtools.compress_indices(mesh) meshtools.compress_indices(mesh)
class Concatenate(unittest.TestCase):
def test(self):
cube = primitives.cube_solid()
# It's a TRIANGLE_STRIP
plane = meshtools.generate_indices(primitives.plane_solid())
concatenated = meshtools.concatenate([cube, plane])
self.assertEqual(concatenated.vertex_count, cube.vertex_count + plane.vertex_count)
self.assertEqual(concatenated.index_count, cube.index_count + plane.index_count)
def test_empty(self):
with self.assertRaisesRegex(AssertionError, "expected at least one mesh"):
meshtools.concatenate([])
def test_invalid_primitive(self):
with self.assertRaisesRegex(AssertionError, "invalid mesh primitive"):
meshtools.concatenate([primitives.cube_solid(), primitives.plane_solid()])
# Should check that also for the first argument
with self.assertRaisesRegex(AssertionError, "invalid mesh primitive"):
meshtools.concatenate([primitives.plane_solid()])
def test_inconsistent_primitive(self):
with self.assertRaisesRegex(AssertionError, "inconsistent mesh primitive"):
meshtools.concatenate([primitives.cube_solid(), primitives.line3d()])
with self.assertRaisesRegex(AssertionError, "inconsistent mesh primitive"):
meshtools.concatenate([primitives.line3d(), primitives.cube_solid()])
class Duplicate(unittest.TestCase): class Duplicate(unittest.TestCase):
def test(self): def test(self):
mesh = primitives.cube_solid() mesh = primitives.cube_solid()

Loading…
Cancel
Save