diff --git a/src/python/magnum/CMakeLists.txt b/src/python/magnum/CMakeLists.txt index 3f2d565..31b3e98 100644 --- a/src/python/magnum/CMakeLists.txt +++ b/src/python/magnum/CMakeLists.txt @@ -84,7 +84,8 @@ endif() if(Magnum_SceneGraph_FOUND) set(magnum_scenegraph_SRCS scenegraph.cpp - scenegraph.matrix.cpp) + scenegraph.matrix.cpp + scenegraph.trs.cpp) pybind11_add_module(magnum_scenegraph ${magnum_scenegraph_SRCS}) target_include_directories(magnum_scenegraph PRIVATE diff --git a/src/python/magnum/scenegraph.cpp b/src/python/magnum/scenegraph.cpp index 8bf8e5d..e609f04 100644 --- a/src/python/magnum/scenegraph.cpp +++ b/src/python/magnum/scenegraph.cpp @@ -168,4 +168,5 @@ PYBIND11_MODULE(scenegraph, m) { magnum::scenegraph(m); magnum::scenegraphMatrix(m); + magnum::scenegraphTrs(m); } diff --git a/src/python/magnum/scenegraph.h b/src/python/magnum/scenegraph.h index dcb4353..135cdce 100644 --- a/src/python/magnum/scenegraph.h +++ b/src/python/magnum/scenegraph.h @@ -81,12 +81,6 @@ template void object(py:: .def("reset_transformation", [](SceneGraph::PyObject>& self) { self.resetTransformation(); }, "Reset the transformation") - .def("transform", [](SceneGraph::PyObject>& self, const typename Transformation::DataType& transformation) { - self.transform(transformation); - }, "Transform the object") - .def("transform_local", [](SceneGraph::PyObject>& self, const typename Transformation::DataType& transformation) { - self.transformLocal(transformation); - }, "Transform the object as a local transformation") .def("translate", [](SceneGraph::PyObject>& self, const VectorTypeFor& vector) { self.translate(vector); }, "Translate the object") @@ -95,6 +89,16 @@ template void object(py:: }, "Translate the object as a local transformation"); } +template void objectTransform(py::class_, SceneGraph::PyObject>, SceneGraph::AbstractObject, SceneGraph::PyObjectHolder>>& c) { + c + .def("transform", [](SceneGraph::PyObject>& self, const typename Transformation::DataType& transformation) { + self.transform(transformation); + }, "Transform the object") + .def("transform_local", [](SceneGraph::PyObject>& self, const typename Transformation::DataType& transformation) { + self.transformLocal(transformation); + }, "Transform the object as a local transformation"); +} + template void object2D(py::class_, SceneGraph::PyObject>, SceneGraph::AbstractObject, SceneGraph::PyObjectHolder>>& c) { c .def("rotate", [](SceneGraph::PyObject>& self, const Radd angle) { @@ -140,16 +144,21 @@ template void objectScale }, "Scale the object") .def("scale_local", [](SceneGraph::PyObject>& self, const VectorTypeFor& vector) { self.scaleLocal(vector); - }, "Scale the object as a local transformation") - .def("reflect", [](SceneGraph::PyObject>& self, const VectorTypeFor& vector) { + }, "Scale the object as a local transformation"); +} + +template void objectReflect(py::class_, SceneGraph::PyObject>, SceneGraph::AbstractObject, SceneGraph::PyObjectHolder>>& c) { + c + .def("reflect", [](SceneGraph::PyObject>& self, const VectorTypeFor& vector) { self.reflect(vector); }, "Reflect the object") - .def("reflect_local", [](SceneGraph::PyObject>& self, const VectorTypeFor& vector) { + .def("reflect_local", [](SceneGraph::PyObject>& self, const VectorTypeFor& vector) { self.reflectLocal(vector); }, "Reflect the object as a local transformation"); } void scenegraphMatrix(py::module& m); +void scenegraphTrs(py::module& m); } diff --git a/src/python/magnum/scenegraph.matrix.cpp b/src/python/magnum/scenegraph.matrix.cpp index 7f84d96..e49b5ce 100644 --- a/src/python/magnum/scenegraph.matrix.cpp +++ b/src/python/magnum/scenegraph.matrix.cpp @@ -42,13 +42,17 @@ void scenegraphMatrix(py::module& m) { py::class_, SceneGraph::PyObject>, SceneGraph::AbstractObject2D, SceneGraph::PyObjectHolder>> object2D_{matrix, "Object2D", "Two-dimensional object with matrix-based transformation implementation"}; object(object2D_); + objectTransform(object2D_); object2D(object2D_); objectScale(object2D_); + objectReflect(object2D_); py::class_, SceneGraph::PyObject>, SceneGraph::AbstractObject3D, SceneGraph::PyObjectHolder>> object3D_{matrix, "Object3D", "Three-dimensional object with matrix-based transformation implementation"}; object(object3D_); + objectTransform(object3D_); object3D(object3D_); objectScale(object3D_); + objectReflect(object3D_); } } diff --git a/src/python/magnum/scenegraph.trs.cpp b/src/python/magnum/scenegraph.trs.cpp new file mode 100644 index 0000000..50afcb8 --- /dev/null +++ b/src/python/magnum/scenegraph.trs.cpp @@ -0,0 +1,76 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include +#include + +#include "scenegraph.h" + +namespace magnum { + +namespace { + +template void objectTrs(py::class_, SceneGraph::PyObject>, SceneGraph::AbstractObject, SceneGraph::PyObjectHolder>>& c) { + c + .def_property("translation", + &SceneGraph::Object::translation, + &SceneGraph::Object::setTranslation, + "Object translation") + .def_property("rotation", + &SceneGraph::Object::rotation, + &SceneGraph::Object::setRotation, + "Object rotation") + .def_property("scaling", + &SceneGraph::Object::scaling, + &SceneGraph::Object::setScaling, + "Object scaling"); +} + +} + +void scenegraphTrs(py::module& m) { + py::module matrix = m.def_submodule("trs"); + matrix.doc() = "Translation/rotation/scaling-based scene graph implementation"; + + py::class_> scene2D_{matrix, "Scene2D", "Two-dimensional scene with TRS-based transformation implementation"}; + scene(scene2D_); + + py::class_> scene3D_{matrix, "Scene3D", "Three-dimensional scene with TRS-based transformation implementation"}; + scene(scene3D_); + + py::class_, SceneGraph::PyObject>, SceneGraph::AbstractObject2D, SceneGraph::PyObjectHolder>> object2D_{matrix, "Object2D", "Two-dimensional object with TRS-based transformation implementation"}; + object(object2D_); + object2D(object2D_); + objectScale(object2D_); + objectTrs(object2D_); + + py::class_, SceneGraph::PyObject>, SceneGraph::AbstractObject3D, SceneGraph::PyObjectHolder>> object3D_{matrix, "Object3D", "Three-dimensional object with TRS-based transformation implementation"}; + object(object3D_); + object3D(object3D_); + objectScale(object3D_); + objectTrs(object3D_); +} + +} diff --git a/src/python/magnum/test/test_scenegraph_trs.py b/src/python/magnum/test/test_scenegraph_trs.py new file mode 100644 index 0000000..efc3910 --- /dev/null +++ b/src/python/magnum/test/test_scenegraph_trs.py @@ -0,0 +1,51 @@ +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 +# Vladimír Vondruš +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# + +import sys +import unittest + +from magnum import * +from magnum import scenegraph +from magnum.scenegraph.trs import Object3D, Scene3D + +class Object(unittest.TestCase): + def test(self): + scene = Scene3D() + + a = Object3D(scene) + a.rotate_local(Deg(35.0), Vector3.x_axis()) + self.assertEqual(a.transformation, Matrix4.rotation_x(Deg(35.0))) + self.assertEqual(a.absolute_transformation(), Matrix4.rotation_x(Deg(35.0))) + + b = Object3D(a) + b.translate((3.0, 4.0, 5.0)) + self.assertEqual(b.transformation, Matrix4.translation((3.0, 4.0, 5.0))) + self.assertEqual(b.absolute_transformation(), + Matrix4.rotation_x(Deg(35.0))@ + Matrix4.translation((3.0, 4.0, 5.0))) + + c = Object3D(scene) + self.assertEqual(c.transformation, Matrix4.identity_init()) + self.assertEqual(c.absolute_transformation(), Matrix4.identity_init())