From bb7627445b9a35f8e03d98bcd965f0450f87662a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 27 Dec 2010 19:08:54 +0100 Subject: [PATCH] Abstract base class for objects. --- src/AbstractObject.cpp | 46 ++++++++++ src/AbstractObject.h | 143 ++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 11 +++ src/Test/AbstractObjectTest.cpp | 43 ++++++++++ src/Test/AbstractObjectTest.h | 41 +++++++++ src/Test/CMakeLists.txt | 1 + 6 files changed, 285 insertions(+) create mode 100644 src/AbstractObject.cpp create mode 100644 src/AbstractObject.h create mode 100644 src/Test/AbstractObjectTest.cpp create mode 100644 src/Test/AbstractObjectTest.h create mode 100644 src/Test/CMakeLists.txt diff --git a/src/AbstractObject.cpp b/src/AbstractObject.cpp new file mode 100644 index 000000000..a3a47c592 --- /dev/null +++ b/src/AbstractObject.cpp @@ -0,0 +1,46 @@ +/* + Copyright © 2010 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "AbstractObject.h" + +using namespace std; + +namespace Magnum { + +void AbstractObject::setParent(AbstractObject* parent) { + if(_parent == parent) return; + + /* Remove the object from old parent children list */ + if(_parent != 0) + _parent->_children.erase(this); + + /* Set new parent and add the object to new parent children list */ + if(parent != 0) { + parent->_children.insert(this); + } + + _parent = parent; +} + +AbstractObject::~AbstractObject() { + /* Remove the object from parent's children */ + setParent(0); + + /* Delete all children */ + for(set::const_iterator it = _children.begin(); it != _children.end(); ++it) + delete *it; +} + +} diff --git a/src/AbstractObject.h b/src/AbstractObject.h new file mode 100644 index 000000000..e215e6399 --- /dev/null +++ b/src/AbstractObject.h @@ -0,0 +1,143 @@ +#ifndef Magnum_AbstractObject_h +#define Magnum_AbstractObject_h +/* + Copyright © 2010 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::AbstractObject + */ + +#include + +#include "Magnum.h" + +namespace Magnum { + +/** + * @brief Base for all positioned objects + * + * @todo Transform transformation when changing parent, so the object stays in + * place. + */ +class AbstractObject { + DISABLE_COPY(AbstractObject) + + public: + /** + * @brief Constructor + * @param parent Parent object + * + * Sets all transformations to their default values. + */ + inline AbstractObject(AbstractObject* parent = 0): _parent(0) { + setParent(parent); + } + + /** + * @brief Destructor + * + * Removes itself from parent's children list and destroys all own + * children. + */ + virtual ~AbstractObject(); + + /** @brief Parent object */ + inline AbstractObject* parent() const { return _parent; } + + /** @brief Child objects */ + const std::set& children() const { return _children; } + + /** @brief Set parent object */ + void setParent(AbstractObject* parent); + + /** @brief Transformation matrix */ + inline Matrix4 transformation() const { return _transformation; } + + /** @brief Set transformation matrix */ + inline void setTransformation(const Matrix4& transformation) { _transformation = transformation; } + + /** + * @brief Multiply transformation matrix + * + * Multiplies current transformation matrix from the + * left by new matrix. + */ + inline void multiplyTransformation(const Matrix4& transformation) { _transformation = transformation*_transformation; } + + /** + * @brief Set transformation and parent from another object + * + * Sets parent and transformation from another object, so they will + * appear in the same place. + */ + inline void setTransformationFrom(const AbstractObject& another) { + setParent(another.parent()); + setTransformation(another.transformation()); + } + + /** + * @brief Translate object + * + * Same as calling multiplyTransformation() with Matrix4::translation(). + */ + inline void translate(Vector3 vec) { + multiplyTransformation(Matrix4::translation(vec)); + } + + /** @copydoc translate(Vector3) */ + inline void translate(GLfloat x, GLfloat y, GLfloat z) { + translate(Vector3(x, y, z)); + } + + /** + * @brief Scale object + * + * Same as calling multiplyTransformation() with Matrix4::scaling(). + */ + inline void scale(Vector3 vec) { + multiplyTransformation(Matrix4::scaling(vec)); + } + + /** @copydoc scale(Vector3) */ + inline void scale(GLfloat x, GLfloat y, GLfloat z) { + scale(Vector3(x, y, z)); + } + + /** + * @brief Rotate object + * + * Same as calling multiplyTransformation() with Matrix4::rotation(). + */ + inline void rotate(GLfloat angle, Vector3 vec) { + multiplyTransformation(Matrix4::rotation(angle, vec)); + } + + /** @copydoc rotate(GLfloat, Vector3) */ + inline void rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { + rotate(angle, Vector3(x, y, z)); + } + + /** @brief Draw object */ + virtual void draw(const Matrix4& transformationMatrix, const Matrix4& projectionMatrix) = 0; + + private: + AbstractObject* _parent; + std::set _children; + Matrix4 _transformation; +}; + +} + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 10d011aa7..114c2830f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,18 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +find_package(OpenGL REQUIRED) +find_package(GLEW REQUIRED) + add_subdirectory(Math) +set(Magnum_SRCS + AbstractObject.cpp +) + +add_library(Magnum SHARED ${Magnum_SRCS}) +target_link_libraries(Magnum ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARY}) + if(BUILD_TESTS) enable_testing() + add_subdirectory(Test) endif() diff --git a/src/Test/AbstractObjectTest.cpp b/src/Test/AbstractObjectTest.cpp new file mode 100644 index 000000000..896fddc47 --- /dev/null +++ b/src/Test/AbstractObjectTest.cpp @@ -0,0 +1,43 @@ +/* + Copyright © 2010 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "AbstractObjectTest.h" + +#include + +QTEST_APPLESS_MAIN(Magnum::Test::AbstractObjectTest) + +namespace Magnum { namespace Test { + +void AbstractObjectTest::parenting() { + Object root; + + Object* childOne = new Object(&root); + Object* childTwo = new Object(&root); + + QVERIFY(childOne->parent() == &root); + QVERIFY(root.children().size() == 2); + + /* Reparent to another */ + childTwo->setParent(childOne); + QVERIFY(root.children().size() == 1 && *root.children().begin() == childOne); + QVERIFY(childOne->children().size() == 1 && *childOne->children().begin() == childTwo); + + /* Delete child */ + delete childTwo; + QVERIFY(childOne->children().size() == 0); +} + +}} diff --git a/src/Test/AbstractObjectTest.h b/src/Test/AbstractObjectTest.h new file mode 100644 index 000000000..40696d469 --- /dev/null +++ b/src/Test/AbstractObjectTest.h @@ -0,0 +1,41 @@ +#ifndef Magnum_Test_AbstractObjectTest_h +#define Magnum_Test_AbstractObjectTest_h +/* + Copyright © 2010 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include + +#include "AbstractObject.h" + +namespace Magnum { namespace Test { + +class Object: public AbstractObject { + public: + inline Object(AbstractObject* parent = 0): AbstractObject(parent) {} + inline virtual void draw(const Magnum::Matrix4& transformationMatrix, const Magnum::Matrix4& projectionMatrix) {} + + inline const std::set& children() { return AbstractObject::children(); } +}; + +class AbstractObjectTest: public QObject { + Q_OBJECT + + private slots: + void parenting(); +}; + +}} + +#endif diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt new file mode 100644 index 000000000..17b1d14fa --- /dev/null +++ b/src/Test/CMakeLists.txt @@ -0,0 +1 @@ +magnum_add_test(AbstractObjectTest AbstractObjectTest.h AbstractObjectTest.cpp Magnum)