Browse Source

python: expose the new meshtools.filter_attributes() as well.

next
Vladimír Vondruš 3 years ago
parent
commit
d8b98c2057
  1. 4
      doc/python/magnum.meshtools.rst
  2. 1
      doc/python/pages/changelog.rst
  3. 14
      src/python/magnum/meshtools.cpp
  4. 36
      src/python/magnum/test/test_meshtools.py

4
doc/python/magnum.meshtools.rst

@ -38,6 +38,10 @@
.. py:function:: magnum.meshtools.duplicate
:raise AssertionError: If :p:`mesh` is not indexed
.. py:function:: magnum.meshtools.filter_attributes
:raise AssertionError: If size of :p:`attributes_to_keep` is different than
:p:`mesh` attribute count
.. py:function:: magnum.meshtools.generate_indices
:raise AssertionError: If :p:`mesh` is not :ref:`MeshPrimitive.LINE_STRIP`,
:ref:`MeshPrimitive.LINE_LOOP`, :ref:`MeshPrimitive.TRIANGLE_STRIP` or

1
doc/python/pages/changelog.rst

@ -109,6 +109,7 @@ Changelog
as flags and not just as an enum
- Exposed :ref:`meshtools.compress_indices()`, :ref:`meshtools.concatenate()`,
:ref:`meshtools.copy()`, :ref:`meshtools.duplicate()`,
:ref:`meshtools.filter_attributes()`,
:ref:`meshtools.filter_except_attributes()`,
:ref:`meshtools.filter_only_attributes()`,
:ref:`meshtools.generate_indices()`, :ref:`meshtools.interleave()`,

14
src/python/magnum/meshtools.cpp

@ -25,8 +25,9 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h> /* for std::vector */
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/ArrayViewStl.h>
#include <Corrade/Containers/BitArrayView.h>
#include <Corrade/Containers/Optional.h>
#include <Magnum/GL/Mesh.h>
#include <Magnum/MeshTools/Compile.h>
#include <Magnum/MeshTools/CompressIndices.h>
@ -131,6 +132,17 @@ void meshtools(py::module_& m) {
return MeshTools::duplicate(mesh);
}, "Duplicate indexed mesh data", py::arg("mesh"))
.def("filter_attributes", [](const Trade::MeshData& mesh, const Containers::BitArrayView attributesToKeep) {
if(attributesToKeep.size() != mesh.attributeCount()) {
PyErr_Format(PyExc_AssertionError, "expected %u bits but got %zu", mesh.attributeCount(), attributesToKeep.size());
throw py::error_already_set{};
}
/* If the mesh already has an owner, use that instead to avoid
long reference chains */
py::object meshOwner = pyObjectHolderFor<Trade::PyDataHolder>(mesh).owner;
return Trade::pyDataHolder(MeshTools::filterAttributes(mesh, attributesToKeep), meshOwner.is_none() ? py::cast(mesh) : std::move(meshOwner));
}, "Filter a mesh to contain only the selected subset of attributes", py::arg("mesh"), py::arg("attributes_to_keep"))
.def("filter_except_attributes", [](const Trade::MeshData& mesh, const std::vector<Trade::MeshAttribute> attributes) {
/* If the mesh already has an owner, use that instead to avoid
long reference chains */

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

@ -27,6 +27,7 @@ import os
import sys
import unittest
from corrade import containers
from magnum import *
from magnum import meshtools, primitives, trade
@ -105,6 +106,41 @@ class GenerateIndices(unittest.TestCase):
meshtools.generate_indices(mesh)
class Filter(unittest.TestCase):
def test(self):
mesh = primitives.cube_solid()
mesh_refcount = sys.getrefcount(mesh)
self.assertEqual(mesh.attribute_count(), 2)
self.assertTrue(mesh.has_attribute(trade.MeshAttribute.NORMAL))
attributes_to_keep = containers.BitArray.value_init(mesh.attribute_count())
attributes_to_keep[mesh.attribute_id(trade.MeshAttribute.NORMAL)] = True
filtered = meshtools.filter_attributes(mesh, attributes_to_keep)
filtered_refcount = sys.getrefcount(filtered)
self.assertEqual(filtered.attribute_count(), 1)
self.assertTrue(filtered.has_attribute(trade.MeshAttribute.NORMAL))
self.assertEqual(sys.getrefcount(mesh), mesh_refcount + 1)
self.assertIs(filtered.owner, mesh)
# Subsequent filtering will still reference the original mesh, not the
# intermediates
filtered2 = meshtools.filter_attributes(filtered, containers.BitArray.direct_init(filtered.attribute_count(), True))
self.assertEqual(filtered2.attribute_count(), 1)
self.assertTrue(filtered2.has_attribute(trade.MeshAttribute.NORMAL))
self.assertEqual(sys.getrefcount(filtered), filtered_refcount)
self.assertEqual(sys.getrefcount(mesh), mesh_refcount + 2)
self.assertIs(filtered2.owner, mesh)
del filtered
self.assertEqual(sys.getrefcount(mesh), mesh_refcount + 1)
del filtered2
self.assertEqual(sys.getrefcount(mesh), mesh_refcount)
def test_invalid_size(self):
with self.assertRaisesRegex(AssertionError, "expected 2 bits but got 3"):
meshtools.filter_attributes(primitives.cube_solid(), containers.BitArray.value_init(3))
def test_only_attributes(self):
mesh = primitives.cube_solid()
mesh_refcount = sys.getrefcount(mesh)

Loading…
Cancel
Save