diff --git a/doc/python/magnum.scenetools.rst b/doc/python/magnum.scenetools.rst index 19c093d..19d6b0e 100644 --- a/doc/python/magnum.scenetools.rst +++ b/doc/python/magnum.scenetools.rst @@ -23,7 +23,7 @@ DEALINGS IN THE SOFTWARE. .. -.. py:function:: magnum.scenetools.flatten_transformation_hierarchy2d +.. py:function:: magnum.scenetools.absolute_field_transformations2d :raise KeyError: If :p:`field` does not exist in :p:`scene` :raise IndexError: If :p:`field_id` negative or not less than :ref:`trade.SceneData.field_count` @@ -31,7 +31,7 @@ :raise AssertionError: If :p:`scene` does not have :ref:`trade.SceneField.PARENT` -.. py:function:: magnum.scenetools.flatten_transformation_hierarchy3d +.. py:function:: magnum.scenetools.absolute_field_transformations3d :raise KeyError: If :p:`field` does not exist in :p:`scene` :raise IndexError: If :p:`field_id` negative or not less than :ref:`trade.SceneData.field_count` diff --git a/doc/python/pages/changelog.rst b/doc/python/pages/changelog.rst index f9bacf5..d699607 100644 --- a/doc/python/pages/changelog.rst +++ b/doc/python/pages/changelog.rst @@ -108,10 +108,11 @@ Changelog :ref:`platform.glfw.Application.InputEvent.Modifier` to behave properly as flags and not just as an enum - Exposed :ref:`meshtools.compress_indices()`, :ref:`meshtools.concatenate()`, - :ref:`meshtools.duplicate()`, :ref:`meshtools.filter_except_attributes()`, + :ref:`meshtools.copy()`, :ref:`meshtools.duplicate()`, + :ref:`meshtools.filter_except_attributes()`, :ref:`meshtools.filter_only_attributes()`, :ref:`meshtools.generate_indices()`, :ref:`meshtools.interleave()`, - :ref:`meshtools.owned()`, :ref:`meshtools.remove_duplicates()`, + :ref:`meshtools.remove_duplicates()`, :ref:`meshtools.remove_duplicates_fuzzy()`, :ref:`meshtools.transform2d()`, :ref:`meshtools.transform2d_in_place()`, :ref:`meshtools.transform3d()`, :ref:`meshtools.transform3d_in_place()`, diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 3e17e0a..13fab47 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -910,7 +910,7 @@ foreach(_component ${Magnum_FIND_COMPONENTS}) # SceneTools library elseif(_component STREQUAL SceneTools) - set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES FlattenTransformationHierarchy.h) + set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES Hierarchy.h) # ShaderTools library elseif(_component STREQUAL ShaderTools) diff --git a/src/python/magnum/meshtools.cpp b/src/python/magnum/meshtools.cpp index 72bc7ff..bfae664 100644 --- a/src/python/magnum/meshtools.cpp +++ b/src/python/magnum/meshtools.cpp @@ -30,13 +30,13 @@ #include #include #include +#include #include #include -#include +#include #include #include #include -#include #include #include @@ -163,7 +163,7 @@ void meshtools(py::module_& m) { test */ return MeshTools::interleave(mesh, {}, flags); }, "Interleave mesh data", py::arg("mesh"), py::arg("flags") = MeshTools::InterleaveFlag::PreserveInterleavedAttributes) - .def("owned", static_cast(MeshTools::owned), "Create an owned mesh data", py::arg("mesh")) + .def("copy", static_cast(MeshTools::copy), "Make a owned copy of the mesh", py::arg("mesh")) /** @todo check that the indices/vertices aren't impl-specific once it's possible to test */ .def("remove_duplicates", static_cast(MeshTools::removeDuplicates), "Remove mesh data duplicates", py::arg("mesh")) diff --git a/src/python/magnum/scenetools.cpp b/src/python/magnum/scenetools.cpp index c466974..de5ecba 100644 --- a/src/python/magnum/scenetools.cpp +++ b/src/python/magnum/scenetools.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include "magnum/bootstrap.h" @@ -46,7 +46,7 @@ void scenetools(py::module_& m) { #endif m - .def("flatten_transformation_hierarchy2d", [](const Trade::SceneData& scene, Trade::SceneField field, const Matrix3& globalTransformation) { + .def("absolute_field_transformations2d", [](const Trade::SceneData& scene, Trade::SceneField field, const Matrix3& globalTransformation) { const Containers::Optional fieldId = scene.findFieldId(field); if(!fieldId) { PyErr_SetNone(PyExc_KeyError); @@ -63,10 +63,10 @@ void scenetools(py::module_& m) { /** @todo maybe do a caster for arrays, finally?! */ std::vector out(scene.fieldSize(*fieldId)); - SceneTools::flattenTransformationHierarchy2DInto(scene, *fieldId, out, globalTransformation); + SceneTools::absoluteFieldTransformations2DInto(scene, *fieldId, out, globalTransformation); return out; - }, "Flatten a 2D transformation hierarchy for given field", py::arg("scene"), py::arg("field"), py::arg("global_transformation") = Matrix3{}) - .def("flatten_transformation_hierarchy2d", [](const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix3& globalTransformation) { + }, "Calculate absolute 2D transformations for given field", py::arg("scene"), py::arg("field"), py::arg("global_transformation") = Matrix3{}) + .def("absolute_field_transformations2d", [](const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix3& globalTransformation) { if(fieldId >= scene.fieldCount()) { PyErr_SetNone(PyExc_IndexError); throw py::error_already_set{}; @@ -82,10 +82,10 @@ void scenetools(py::module_& m) { /** @todo maybe do a caster for arrays, finally?! */ std::vector out(scene.fieldSize(fieldId)); - SceneTools::flattenTransformationHierarchy2DInto(scene, fieldId, out, globalTransformation); + SceneTools::absoluteFieldTransformations2DInto(scene, fieldId, out, globalTransformation); return out; - }, "Flatten a 2D transformation hierarchy for given field ID", py::arg("scene"), py::arg("field_id"), py::arg("global_transformation") = Matrix3{}) - .def("flatten_transformation_hierarchy3d", [](const Trade::SceneData& scene, Trade::SceneField field, const Matrix4& globalTransformation) { + }, "Calculate absolute 2D transformations for given named field", py::arg("scene"), py::arg("field_id"), py::arg("global_transformation") = Matrix3{}) + .def("absolute_field_transformations3d", [](const Trade::SceneData& scene, Trade::SceneField field, const Matrix4& globalTransformation) { const Containers::Optional fieldId = scene.findFieldId(field); if(!fieldId) { PyErr_SetNone(PyExc_KeyError); @@ -102,10 +102,10 @@ void scenetools(py::module_& m) { /** @todo maybe do a caster for arrays, finally?! */ std::vector out(scene.fieldSize(*fieldId)); - SceneTools::flattenTransformationHierarchy3DInto(scene, *fieldId, out, globalTransformation); + SceneTools::absoluteFieldTransformations3DInto(scene, *fieldId, out, globalTransformation); return out; - }, "Flatten a 3D transformation hierarchy for given field", py::arg("scene"), py::arg("field"), py::arg("global_transformation") = Matrix4{}) - .def("flatten_transformation_hierarchy3d", [](const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix4& globalTransformation) { + }, "Calculate absolute 3D transformations for given field", py::arg("scene"), py::arg("field"), py::arg("global_transformation") = Matrix4{}) + .def("absolute_field_transformations3d", [](const Trade::SceneData& scene, UnsignedInt fieldId, const Matrix4& globalTransformation) { if(fieldId >= scene.fieldCount()) { PyErr_SetNone(PyExc_IndexError); throw py::error_already_set{}; @@ -121,9 +121,9 @@ void scenetools(py::module_& m) { /** @todo maybe do a caster for arrays, finally?! */ std::vector out(scene.fieldSize(fieldId)); - SceneTools::flattenTransformationHierarchy3DInto(scene, fieldId, out, globalTransformation); + SceneTools::absoluteFieldTransformations3DInto(scene, fieldId, out, globalTransformation); return out; - }, "Flatten a 3D transformation hierarchy for given field ID", py::arg("scene"), py::arg("field_id"), py::arg("global_transformation") = Matrix4{}); + }, "Calculate absolute 2D transformations for given named field", py::arg("scene"), py::arg("field_id"), py::arg("global_transformation") = Matrix4{}); } } diff --git a/src/python/magnum/test/test_meshtools.py b/src/python/magnum/test/test_meshtools.py index 50d52d3..0dfdf53 100644 --- a/src/python/magnum/test/test_meshtools.py +++ b/src/python/magnum/test/test_meshtools.py @@ -180,13 +180,13 @@ class Interleave(unittest.TestCase): # Gap after normals removed self.assertEqual(interleaved_packed.attribute_stride(trade.MeshAttribute.POSITION), 12 + 8) -class Owned(unittest.TestCase): +class Copy(unittest.TestCase): def test(self): mesh = primitives.square_solid() self.assertEqual(mesh.vertex_data_flags, trade.DataFlags.GLOBAL) - owned = meshtools.owned(mesh) - self.assertEqual(owned.vertex_data_flags, trade.DataFlags.OWNED|trade.DataFlags.MUTABLE) + copy = meshtools.copy(mesh) + self.assertEqual(copy.vertex_data_flags, trade.DataFlags.OWNED|trade.DataFlags.MUTABLE) class RemoveDuplicates(unittest.TestCase): def test(self): @@ -248,14 +248,14 @@ class Transform(unittest.TestCase): self.assertEqual(transformed.attribute(trade.MeshAttribute.TEXTURE_COORDINATES)[0], (101.0, 0.0)) def test_texture_coordinates2d_in_place(self): - mesh = meshtools.owned(primitives.square_solid(primitives.SquareFlags.TEXTURE_COORDINATES)) + mesh = meshtools.copy(primitives.square_solid(primitives.SquareFlags.TEXTURE_COORDINATES)) self.assertEqual(mesh.attribute(trade.MeshAttribute.TEXTURE_COORDINATES)[0], (1.0, 0.0)) meshtools.transform_texture_coordinates2d_in_place(mesh, Matrix3.translation(Vector2.x_axis(100.0))) self.assertEqual(mesh.attribute(trade.MeshAttribute.TEXTURE_COORDINATES)[0], (101.0, 0.0)) def test_no_attribute(self): - mesh = meshtools.owned(primitives.square_solid(primitives.SquareFlags.TEXTURE_COORDINATES)) + mesh = meshtools.copy(primitives.square_solid(primitives.SquareFlags.TEXTURE_COORDINATES)) with self.assertRaisesRegex(KeyError, "position attribute not found"): meshtools.transform2d(mesh, Matrix3(), 1) diff --git a/src/python/magnum/test/test_scenetools.py b/src/python/magnum/test/test_scenetools.py index 6bfe3d4..7268cd2 100644 --- a/src/python/magnum/test/test_scenetools.py +++ b/src/python/magnum/test/test_scenetools.py @@ -30,8 +30,8 @@ from magnum import * from magnum import scenetools, trade import magnum -class FlattenTransformationHierarchy(unittest.TestCase): - def test_2d(self): +class Hierarchy(unittest.TestCase): + def test_absolute_field_transformations2d(self): # Static builds with non-static plugins cause assertions with non-owned # array deleters used by PrimitiveImporter, skip in that case if magnum.BUILD_STATIC: @@ -44,30 +44,14 @@ class FlattenTransformationHierarchy(unittest.TestCase): scene = importer.scene(0) self.assertTrue(scene.is_2d) - transformations = scenetools.flatten_transformation_hierarchy2d(scene, trade.SceneField.MESH) - self.assertEqual(len(transformations), scene.field_size(trade.SceneField.MESH)) - self.assertEqual(transformations[0], Matrix3.translation((-4.5, -3.0))) + transformations1 = scenetools.absolute_field_transformations2d(scene, trade.SceneField.MESH) + transformations2 = scenetools.absolute_field_transformations2d(scene, scene.field_id(trade.SceneField.MESH)) + self.assertEqual(len(transformations1), scene.field_size(trade.SceneField.MESH)) + self.assertEqual(len(transformations2), scene.field_size(trade.SceneField.MESH)) + self.assertEqual(transformations1[0], Matrix3.translation((-4.5, -3.0))) + self.assertEqual(transformations2[0], Matrix3.translation((-4.5, -3.0))) - def test_2d_field_id(self): - # Static builds with non-static plugins cause assertions with non-owned - # array deleters used by PrimitiveImporter, skip in that case - if magnum.BUILD_STATIC: - self.skipTest("dynamic PrimitiveImporter doesn't work with a static build") - - # The only way to get a 2D scene is via PrimitiveImporter - importer = trade.ImporterManager().load_and_instantiate('PrimitiveImporter') - importer.open_data(containers.ArrayView()) - - scene = importer.scene(0) - self.assertTrue(scene.is_2d) - - mesh_field = scene.field_id(trade.SceneField.MESH) - - transformations = scenetools.flatten_transformation_hierarchy2d(scene, mesh_field) - self.assertEqual(len(transformations), scene.field_size(mesh_field)) - self.assertEqual(transformations[0], Matrix3.translation((-4.5, -3.0))) - - def test_3d(self): + def test_absolute_field_transformations3d(self): # Static builds with non-static plugins cause assertions with non-owned # array deleters used by PrimitiveImporter, skip in that case if magnum.BUILD_STATIC: @@ -79,29 +63,14 @@ class FlattenTransformationHierarchy(unittest.TestCase): scene = importer.scene(1) self.assertTrue(scene.is_3d) - transformations = scenetools.flatten_transformation_hierarchy3d(scene, trade.SceneField.MESH) - self.assertEqual(len(transformations), scene.field_size(trade.SceneField.MESH)) - self.assertEqual(transformations[0], Matrix4.translation((-4.5, -3.0, 0.0))) - - def test_3d_field_id(self): - # Static builds with non-static plugins cause assertions with non-owned - # array deleters used by PrimitiveImporter, skip in that case - if magnum.BUILD_STATIC: - self.skipTest("dynamic PrimitiveImporter doesn't work with a static build") - - importer = trade.ImporterManager().load_and_instantiate('PrimitiveImporter') - importer.open_data(containers.ArrayView()) - - scene = importer.scene(1) - self.assertTrue(scene.is_3d) - - mesh_field = scene.field_id(trade.SceneField.MESH) - - transformations = scenetools.flatten_transformation_hierarchy3d(scene, mesh_field) - self.assertEqual(len(transformations), scene.field_size(mesh_field)) - self.assertEqual(transformations[0], Matrix4.translation((-4.5, -3.0, 0.0))) + transformations1 = scenetools.absolute_field_transformations3d(scene, trade.SceneField.MESH) + transformations2 = scenetools.absolute_field_transformations3d(scene, scene.field_id(trade.SceneField.MESH)) + self.assertEqual(len(transformations1), scene.field_size(trade.SceneField.MESH)) + self.assertEqual(len(transformations2), scene.field_size(trade.SceneField.MESH)) + self.assertEqual(transformations1[0], Matrix4.translation((-4.5, -3.0, 0.0))) + self.assertEqual(transformations2[0], Matrix4.translation((-4.5, -3.0, 0.0))) - def test_field_not_found(self): + def test_absolute_field_transformations_not_found(self): # Static builds with non-static plugins cause assertions with non-owned # array deleters used by PrimitiveImporter, skip in that case if magnum.BUILD_STATIC: @@ -113,15 +82,15 @@ class FlattenTransformationHierarchy(unittest.TestCase): scene = importer.scene(0) with self.assertRaises(KeyError): - scenetools.flatten_transformation_hierarchy2d(scene, trade.SceneField.LIGHT) + scenetools.absolute_field_transformations2d(scene, trade.SceneField.LIGHT) with self.assertRaises(KeyError): - scenetools.flatten_transformation_hierarchy3d(scene, trade.SceneField.LIGHT) + scenetools.absolute_field_transformations3d(scene, trade.SceneField.LIGHT) with self.assertRaises(IndexError): - scenetools.flatten_transformation_hierarchy2d(scene, scene.field_count) + scenetools.absolute_field_transformations2d(scene, scene.field_count) with self.assertRaises(IndexError): - scenetools.flatten_transformation_hierarchy3d(scene, scene.field_count) + scenetools.absolute_field_transformations3d(scene, scene.field_count) - def test_not_2d_not_3d(self): + def test_absolute_field_transformations_not_2d_not_3d(self): # Static builds with non-static plugins cause assertions with non-owned # array deleters used by PrimitiveImporter, skip in that case if magnum.BUILD_STATIC: @@ -136,15 +105,15 @@ class FlattenTransformationHierarchy(unittest.TestCase): self.assertFalse(scene3d.is_2d) with self.assertRaisesRegex(AssertionError, "the scene is not 2D"): - scenetools.flatten_transformation_hierarchy2d(scene3d, trade.SceneField.MESH) + scenetools.absolute_field_transformations2d(scene3d, trade.SceneField.MESH) with self.assertRaisesRegex(AssertionError, "the scene is not 2D"): - scenetools.flatten_transformation_hierarchy2d(scene3d, scene2d.field_id(trade.SceneField.MESH)) + scenetools.absolute_field_transformations2d(scene3d, scene2d.field_id(trade.SceneField.MESH)) with self.assertRaisesRegex(AssertionError, "the scene is not 3D"): - scenetools.flatten_transformation_hierarchy3d(scene2d, trade.SceneField.MESH) + scenetools.absolute_field_transformations3d(scene2d, trade.SceneField.MESH) with self.assertRaisesRegex(AssertionError, "the scene is not 3D"): - scenetools.flatten_transformation_hierarchy3d(scene2d, scene3d.field_id(trade.SceneField.MESH)) + scenetools.absolute_field_transformations3d(scene2d, scene3d.field_id(trade.SceneField.MESH)) - def test_no_hierarchy(self): + def test_absolute_field_transformations_no_hierarchy(self): # TODO implement once it's possible to create / import a scene without # the parent field pass