Browse Source

Merge branch 'master' into compatibility

Vladimír Vondruš 13 years ago
parent
commit
89820a12c3
  1. 16
      README.md
  2. 2
      doc/debug-tools.dox
  3. 15
      doc/mainpage.dox
  4. 28
      doc/platform.dox
  5. 1
      src/DebugTools/CMakeLists.txt
  6. 5
      src/DebugTools/ForceRenderer.h
  7. 68
      src/DebugTools/Implementation/LineSegmentRenderer.cpp
  8. 47
      src/DebugTools/Implementation/LineSegmentRenderer.h
  9. 39
      src/DebugTools/Implementation/LineSegmentRendererTransformation.h
  10. 4
      src/DebugTools/Implementation/SphereRenderer.cpp
  11. 4
      src/DebugTools/ObjectRenderer.h
  12. 8
      src/DebugTools/ShapeRenderer.cpp
  13. 4
      src/DebugTools/ShapeRenderer.h
  14. 1
      src/DebugTools/Test/CMakeLists.txt
  15. 67
      src/DebugTools/Test/LineSegmentRendererTest.cpp
  16. 2
      src/Math/Algorithms/Svd.h
  17. 3
      src/Math/Functions.h
  18. 2
      src/Math/Geometry/Rectangle.h
  19. 22
      src/Math/Test/Vector2Test.cpp
  20. 6
      src/Math/Test/Vector3Test.cpp
  21. 7
      src/Math/Vector.h
  22. 24
      src/Math/Vector2.h
  23. 8
      src/Math/Vector3.h
  24. 6
      src/Platform/AbstractXApplication.cpp
  25. 17
      src/Platform/GlutApplication.cpp
  26. 19
      src/Platform/GlutApplication.h
  27. 2
      src/Platform/GlxContextHandler.cpp
  28. 29
      src/Platform/NaClApplication.cpp
  29. 3
      src/Platform/NaClApplication.h
  30. 50
      src/Platform/Sdl2Application.cpp
  31. 45
      src/Platform/Sdl2Application.h
  32. 2
      src/Platform/WindowlessGlxApplication.cpp
  33. 2
      src/Primitives/CMakeLists.txt
  34. 45
      src/Primitives/Line.cpp
  35. 67
      src/Primitives/Line.h
  36. 18
      src/SceneGraph/Object.hpp
  37. 62
      src/SceneGraph/Test/ObjectTest.cpp
  38. 5
      src/Timeline.h

16
README.md

@ -1,4 +1,4 @@
Magnum is 2D/3D graphics engine written in C++11 and OpenGL 3 Core Profile.
Magnum is 2D/3D graphics engine written in C++11 and modern OpenGL.
DESIGN GOALS
============
@ -34,6 +34,18 @@ DESIGN GOALS
done on top of pre-made skeleton classes, support for file formats is done
using plugins and platform support is done by writing simple wrapper class.
SUPPORTED PLATFORMS
===================
* **OpenGL** 2.1 through 4.3, core profile functionality and modern
extensions
* **OpenGL ES** 2.0, 3.0 and extensions to match desktop OpenGL functionality
* **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through
GLUT or SDL2 toolkit)
* **Windows** (through GLUT or SDL2 toolkit)
* **Google Chrome Native Client** (natively using PPAPI, both `newlib`
and `glibc` toolchains are supported)
FEATURES
========
@ -46,8 +58,6 @@ FEATURES
* Extensible scene graph which can be modified for each specific usage.
* Plugin-based data exchange framework, tools for manipulating meshes,
textures and images.
* Integration with various windowing toolkits and also ability to create
windowless contexts.
* Pre-made shaders, primitives and other tools for easy prototyping and
debugging.

2
doc/debug-tools.dox

@ -63,7 +63,7 @@ SceneGraph::DrawableGroup3D debugDrawables;
// Create renderer options which will be referenced later by "my" resource key
DebugTools::ResourceManager::instance()->set("my",
(new DebugTools::ObjectRendererOptions())->setSize(0.3f));
(new DebugTools::ObjectRendererOptions)->setSize(0.3f));
// Create debug renderer for given object, use "my" options for it. The
// renderer is automatically added to the object features and also to

15
doc/mainpage.dox

@ -25,7 +25,7 @@
namespace Magnum {
/** @mainpage
%Magnum is 2D/3D graphics engine written in C++11 and OpenGL 3 Core Profile.
%Magnum is 2D/3D graphics engine written in C++11 and modern OpenGL.
@section mainpage-design-goals Design goals
@ -60,6 +60,17 @@ namespace Magnum {
done on top of pre-made skeleton classes, support for file formats is done
using plugins and platform support is done by writing simple wrapper class.
@section mainpage-platforms Supported platforms
- **OpenGL** 2.1 through 4.3, core profile functionality and modern
extensions
- **OpenGL ES** 2.0, 3.0 and extensions to match desktop OpenGL functionality
- **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through
GLUT or SDL2 toolkit)
- **Windows** (through GLUT or SDL2 toolkit)
- **Google Chrome Native Client** (natively using PPAPI, both `newlib`
and `glibc` toolchains are supported)
@section mainpage-features Features
- Vector and matrix library with implementation of complex numbers,
@ -69,8 +80,6 @@ namespace Magnum {
- Extensible scene graph which can be modified for each specific usage.
- Plugin-based data exchange framework, tools for manipulating meshes,
textures and images.
- Integration with various windowing toolkits and also ability to create
windowless contexts. Ported to OpenGL ES and various platforms.
- Pre-made shaders, primitives and other tools for easy prototyping and
debugging.

28
doc/platform.dox

@ -147,7 +147,7 @@ window size 800x600 pixels). If you want something else, you can pass
constructor. Using method chaining it can be done conveniently like this:
@code
MyApplication::MyApplication(int& argc, char** argv):
Platform::GlutApplication(argc, argv, (new Configuration())
Platform::GlutApplication(argc, argv, (new Configuration)
->setTitle("My Application")->setSize({800, 600}) {
// ...
}
@ -161,7 +161,7 @@ instead of Configuration instance and then specify it later with
MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication(argc, argv, nullptr) {
// ...
createContext((new Configuration())
createContext((new Configuration)
->setTitle("My Application")
->setSize(size));
@ -169,5 +169,29 @@ MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication(
}
@endcode
The configuration passed to constructor and @ref GlutApplication::createContext() "createContext()"
is automaticall deleted afterwards and if the context creation fails, the
application exits. However, it is also possible to negotiate the context using
@ref GlutApplication::tryCreateContext() "tryCreateContext()". The major
difference is that this function returns `false` instead of exiting and it
doesn't delete the configuration afterwards so you can reuse it. You can for
example try enabling MSAA and if the context creation fails, fall back to
no-AA rendering:
@code
MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication(argc, argv, nullptr) {
// ...
auto conf = new Configuration;
conf->setTitle("My Application")
->setSampleCount(16);
if(!tryCreateContext(conf))
createContext(conf->setSampleCount(0));
else delete conf;
// ...
}
@endcode
*/
}}

1
src/DebugTools/CMakeLists.txt

@ -33,6 +33,7 @@ set(MagnumDebugTools_SRCS
Implementation/AbstractShapeRenderer.cpp
Implementation/AxisAlignedBoxRenderer.cpp
Implementation/BoxRenderer.cpp
Implementation/LineSegmentRenderer.cpp
Implementation/PointRenderer.cpp
Implementation/SphereRenderer.cpp)

5
src/DebugTools/ForceRenderer.h

@ -90,9 +90,8 @@ See @ref debug-tools-renderers for more information.
Example code:
@code
// Create some options
DebugTools::ResourceManager::instance()->set("my", (new DebugTools::ForceRendererOptions()
->setScale(5.0f)
->setColor(Color3<>::fromHSV(120.0_degf, 1.0f, 0.7f)));
DebugTools::ResourceManager::instance()->set("my", (new DebugTools::ForceRendererOptions)
->setScale(5.0f)->setColor(Color3<>::fromHSV(120.0_degf, 1.0f, 0.7f)));
// Create debug renderer for given object, use "my" options for it
Object3D* object;

68
src/DebugTools/Implementation/LineSegmentRenderer.cpp

@ -0,0 +1,68 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
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 "LineSegmentRenderer.h"
#include "Mesh.h"
#include "DebugTools/ShapeRenderer.h"
#include "Physics/Line.h"
#include "Primitives/Line.h"
#include "Shaders/FlatShader.h"
#include "Trade/MeshData2D.h"
#include "Trade/MeshData3D.h"
#include "DebugTools/Implementation/LineSegmentRendererTransformation.h"
namespace Magnum { namespace DebugTools { namespace Implementation {
namespace {
template<UnsignedInt dimensions> ResourceKey meshKey();
template<> inline ResourceKey meshKey<2>() { return ResourceKey("line2d"); }
template<> inline ResourceKey meshKey<3>() { return ResourceKey("line3d"); }
template<UnsignedInt dimensions> ResourceKey vertexBufferKey();
template<> inline ResourceKey vertexBufferKey<2>() { return ResourceKey("line2d-vertices"); }
template<> inline ResourceKey vertexBufferKey<3>() { return ResourceKey("line3d-vertices"); }
template<UnsignedInt dimensions> typename MeshData<dimensions>::Type meshData();
template<> inline Trade::MeshData2D meshData<2>() { return Primitives::Line2D::wireframe(); }
template<> inline Trade::MeshData3D meshData<3>() { return Primitives::Line3D::wireframe(); }
}
template<UnsignedInt dimensions> LineSegmentRenderer<dimensions>::LineSegmentRenderer(Physics::Line<dimensions>& line): AbstractShapeRenderer<dimensions>(meshKey<dimensions>(), vertexBufferKey<dimensions>(), {}), line(line) {
if(!this->mesh) this->createResources(meshData<dimensions>());
}
template<UnsignedInt dimensions> void LineSegmentRenderer<dimensions>::draw(Resource<ShapeRendererOptions>& options, const typename DimensionTraits<dimensions>::MatrixType& projectionMatrix) {
this->shader->setTransformationProjectionMatrix(projectionMatrix*
Implementation::lineSegmentRendererTransformation<dimensions>(line.transformedA(), line.transformedB()))
->setColor(options->color())
->use();
this->mesh->draw();
}
template class LineSegmentRenderer<2>;
template class LineSegmentRenderer<3>;
}}}

47
src/DebugTools/Implementation/LineSegmentRenderer.h

@ -0,0 +1,47 @@
#ifndef Magnum_DebugTools_Implementation_LineSegmentRenderer_h
#define Magnum_DebugTools_Implementation_LineSegmentRenderer_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
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 "AbstractShapeRenderer.h"
#include "Physics/Physics.h"
#include "corradeCompatibility.h"
namespace Magnum { namespace DebugTools { namespace Implementation {
template<UnsignedInt dimensions> class LineSegmentRenderer: public AbstractShapeRenderer<dimensions> {
public:
LineSegmentRenderer(Physics::Line<dimensions>& line);
void draw(Resource<ShapeRendererOptions>& options, const typename DimensionTraits<dimensions>::MatrixType& projectionMatrix) override;
private:
Physics::Line<dimensions>& line;
};
}}}
#endif

39
src/DebugTools/Implementation/LineSegmentRendererTransformation.h

@ -0,0 +1,39 @@
#ifndef Magnum_DebugTools_Implementation_LineSegmentRendererTransformation_h
#define Magnum_DebugTools_Implementation_LineSegmentRendererTransformation_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
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 "DimensionTraits.h"
namespace Magnum { namespace DebugTools { namespace Implementation {
template<UnsignedInt dimensions> typename DimensionTraits<dimensions>::MatrixType lineSegmentRendererTransformation(const typename DimensionTraits<dimensions>::VectorType& a, const typename DimensionTraits<dimensions>::VectorType& b) {
auto transformation = DimensionTraits<dimensions>::MatrixType::translation(a);
transformation.right() = b - a;
return transformation;
}
}}}
#endif

4
src/DebugTools/Implementation/SphereRenderer.cpp

@ -41,8 +41,8 @@ template<UnsignedInt dimensions> SphereRenderer<dimensions>::SphereRenderer(Phys
template<UnsignedInt dimensions> void SphereRenderer<dimensions>::draw(Resource<ShapeRendererOptions>& options, const typename DimensionTraits<dimensions>::MatrixType& projectionMatrix) {
this->shader->setTransformationProjectionMatrix(projectionMatrix*
DimensionTraits<dimensions>::MatrixType::translation(sphere.position())*
DimensionTraits<dimensions>::MatrixType::scaling(typename DimensionTraits<dimensions>::VectorType(sphere.radius())))
DimensionTraits<dimensions>::MatrixType::translation(sphere.transformedPosition())*
DimensionTraits<dimensions>::MatrixType::scaling(typename DimensionTraits<dimensions>::VectorType(sphere.transformedRadius())))
->setColor(options->color())
->use();
this->mesh->draw();

4
src/DebugTools/ObjectRenderer.h

@ -74,8 +74,8 @@ Visualizes object position, rotation and scale using colored axes. See
Example code:
@code
// Create some options
DebugTools::ResourceManager::instance()->set("my",
(new DebugTools::ObjectRendererOptions())->setSize(0.3f));
DebugTools::ResourceManager::instance()->set("my", (new DebugTools::ObjectRendererOptions)
->setSize(0.3f));
// Create debug renderer for given object, use "my" options for it
Object3D* object;

8
src/DebugTools/ShapeRenderer.cpp

@ -29,6 +29,7 @@
#include "Physics/AxisAlignedBox.h"
#include "Physics/Box.h"
#include "Physics/ObjectShape.h"
#include "Physics/LineSegment.h"
#include "Physics/Point.h"
#include "Physics/ShapeGroup.h"
#include "Physics/Sphere.h"
@ -36,6 +37,7 @@
#include "Implementation/AxisAlignedBoxRenderer.h"
#include "Implementation/BoxRenderer.h"
#include "Implementation/LineSegmentRenderer.h"
#include "Implementation/PointRenderer.h"
#include "Implementation/SphereRenderer.h"
@ -52,6 +54,9 @@ template<> void createDebugMesh(ShapeRenderer<2>* renderer, Physics::AbstractSha
case Physics::AbstractShape2D::Type::Box:
renderer->renderers.push_back(new Implementation::BoxRenderer<2>(*static_cast<Physics::Box2D*>(shape)));
break;
case Physics::AbstractShape2D::Type::LineSegment:
renderer->renderers.push_back(new Implementation::LineSegmentRenderer<2>(*static_cast<Physics::LineSegment2D*>(shape)));
break;
case Physics::AbstractShape2D::Type::Point:
renderer->renderers.push_back(new Implementation::PointRenderer<2>(*static_cast<Physics::Point2D*>(shape)));
break;
@ -76,6 +81,9 @@ template<> void createDebugMesh(ShapeRenderer<3>* renderer, Physics::AbstractSha
case Physics::AbstractShape3D::Type::Box:
renderer->renderers.push_back(new Implementation::BoxRenderer<3>(*static_cast<Physics::Box3D*>(shape)));
break;
case Physics::AbstractShape3D::Type::LineSegment:
renderer->renderers.push_back(new Implementation::LineSegmentRenderer<3>(*static_cast<Physics::LineSegment3D*>(shape)));
break;
case Physics::AbstractShape3D::Type::Point:
renderer->renderers.push_back(new Implementation::PointRenderer<3>(*static_cast<Physics::Point3D*>(shape)));
break;

4
src/DebugTools/ShapeRenderer.h

@ -104,8 +104,8 @@ Visualizes collision shapes using wireframe primitives. See
Example code:
@code
// Create some options
DebugTools::ResourceManager::instance()->set("red",
(new DebugTools::ShapeRendererOptions())->setColor({1.0f, 0.0f, 0.0f}));
DebugTools::ResourceManager::instance()->set("red", (new DebugTools::ShapeRendererOptions)
->setColor({1.0f, 0.0f, 0.0f}));
// Create debug renderer for given shape, use "red" options for it
Physics::ObjectShape2D* shape;

1
src/DebugTools/Test/CMakeLists.txt

@ -23,3 +23,4 @@
#
corrade_add_test(DebugToolsForceRendererTest ForceRendererTest.cpp LIBRARIES MagnumMathTestLib)
corrade_add_test(DebugToolsLineSegmentRendererTest LineSegmentRendererTest.cpp LIBRARIES MagnumMathTestLib)

67
src/DebugTools/Test/LineSegmentRendererTest.cpp

@ -0,0 +1,67 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
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 <TestSuite/Tester.h>
#include "Math/Matrix3.h"
#include "Math/Matrix4.h"
#include "Magnum.h"
#include "DebugTools/Implementation/LineSegmentRendererTransformation.h"
namespace Magnum { namespace DebugTools { namespace Test {
class LineSegmentRendererTest: public Corrade::TestSuite::Tester {
public:
explicit LineSegmentRendererTest();
void line2D();
void line3D();
};
LineSegmentRendererTest::LineSegmentRendererTest() {
addTests({&LineSegmentRendererTest::line2D,
&LineSegmentRendererTest::line3D});
}
void LineSegmentRendererTest::line2D() {
const Vector2 a(-2.0f, 3.0f);
const Vector2 b(3.4f, -1.5f);
const Matrix3 matrix = Implementation::lineSegmentRendererTransformation<2>(a, b);
CORRADE_COMPARE(matrix.transformPoint({0.0f, 0.0f}), a);
CORRADE_COMPARE(matrix.transformPoint({1.0f, 0.0f}), b);
}
void LineSegmentRendererTest::line3D() {
const Vector3 a(-2.0f, 3.0f, 1.5f);
const Vector3 b(3.4f, -1.5f, 0.5f);
const Matrix4 matrix = Implementation::lineSegmentRendererTransformation<3>(a, b);
CORRADE_COMPARE(matrix.transformPoint({0.0f, 0.0f, 0.0f}), a);
CORRADE_COMPARE(matrix.transformPoint({1.0f, 0.0f, 0.0f}), b);
}
}}}
CORRADE_TEST_MAIN(Magnum::DebugTools::Test::LineSegmentRendererTest)

2
src/Math/Algorithms/Svd.h

@ -49,7 +49,7 @@ template<class T> T pythagoras(T a, T b) {
return absb*std::sqrt(T(1) + Math::pow<2>(absa/absb));
}
template<class T> T smallestDelta();
template<class T> constexpr T smallestDelta();
template<> inline constexpr Float smallestDelta<Float>() { return 1.0e-32; }
#ifndef MAGNUM_TARGET_GLES
template<> inline constexpr Double smallestDelta<Double>() { return 1.0e-64; }

3
src/Math/Functions.h

@ -164,8 +164,7 @@ template<std::size_t size, class T> Vector<size, T> max(const Vector<size, T>& a
/**
@brief Sign
Returns `1.0` if @f$ x > 0 @f$, `0.0` if @f$ @p x = 0 @f$ and `-1.0` if
@f$ x < 0 @f$.
Returns `1` if @p x > 0, `0` if @p x = 0 and `-1` if @p x < 0.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T sign(const T scalar);

2
src/Math/Geometry/Rectangle.h

@ -60,7 +60,7 @@ template<class T> class Rectangle {
*
* Construct zero-area rectangle positioned at origin.
*/
inline constexpr Rectangle() = default;
inline constexpr Rectangle() {}
/** @brief Construct rectangle from two corners */
inline constexpr Rectangle(const Vector2<T>& bottomLeft, const Vector2<T>& topRight): _bottomLeft(bottomLeft), _topRight(topRight) {}

22
src/Math/Test/Vector2Test.cpp

@ -26,7 +26,7 @@
#include <TestSuite/Tester.h>
#include <Utility/Configuration.h>
#include "Math/Vector2.h"
#include "Math/Vector3.h"
struct Vec2 {
float x, y;
@ -63,13 +63,16 @@ class Vector2Test: public Corrade::TestSuite::Tester {
void convert();
void access();
void cross();
void axes();
void scales();
void perpendicular();
void debug();
void configuration();
};
typedef Math::Vector3<Int> Vector3i;
typedef Math::Vector2<Float> Vector2;
typedef Math::Vector2<Int> Vector2i;
@ -83,8 +86,10 @@ Vector2Test::Vector2Test() {
&Vector2Test::convert,
&Vector2Test::access,
&Vector2Test::cross,
&Vector2Test::axes,
&Vector2Test::scales,
&Vector2Test::perpendicular,
&Vector2Test::debug,
&Vector2Test::configuration});
@ -167,6 +172,14 @@ void Vector2Test::access() {
CORRADE_COMPARE(y, -2.0f);
}
void Vector2Test::cross() {
Vector2i a(1, -1);
Vector2i b(4, 3);
CORRADE_COMPARE(Vector2i::cross(a, b), 7);
CORRADE_COMPARE(Vector3i::cross({a, 0}, {b, 0}), Vector3i(0, 0, Vector2i::cross(a, b)));
}
void Vector2Test::axes() {
constexpr Vector2 x = Vector2::xAxis(5.0f);
constexpr Vector2 y = Vector2::yAxis(6.0f);
@ -181,6 +194,13 @@ void Vector2Test::scales() {
CORRADE_COMPARE(y, Vector2(1.0f, -0.2f));
}
void Vector2Test::perpendicular() {
const Vector2 a(0.5f, -15.0f);
CORRADE_COMPARE(a.perpendicular(), Vector2(15.0f, 0.5f));
CORRADE_COMPARE(Vector2::dot(a.perpendicular(), a), 0.0f);
CORRADE_COMPARE(Vector2::xAxis().perpendicular(), Vector2::yAxis());
}
void Vector2Test::debug() {
std::ostringstream o;
Debug(&o) << Vector2(0.5f, 15.0f);

6
src/Math/Test/Vector3Test.cpp

@ -185,10 +185,10 @@ void Vector3Test::access() {
}
void Vector3Test::cross() {
Vector3 a(1, -1, 1);
Vector3 b(4, 3, 7);
Vector3i a(1, -1, 1);
Vector3i b(4, 3, 7);
CORRADE_COMPARE(Vector3::cross(a, b), Vector3(-10, -3, 7));
CORRADE_COMPARE(Vector3i::cross(a, b), Vector3i(-10, -3, 7));
}
void Vector3Test::axes() {

7
src/Math/Vector.h

@ -84,10 +84,12 @@ template<std::size_t size, class T> class Vector {
/**
* @brief Dot product
*
* @f[
* Returns `0` if two vectors are orthogonal, `1` if two *normalized*
* vectors are parallel and `-1` if two *normalized* vectors are
* antiparallel. @f[
* \boldsymbol a \cdot \boldsymbol b = \sum_{i=0}^{n-1} \boldsymbol a_i \boldsymbol b_i
* @f]
* @see dot() const
* @see dot() const, operator-(), Vector2::perpendicular()
*/
inline static T dot(const Vector<size, T>& a, const Vector<size, T>& b) {
return (a*b).sum();
@ -278,6 +280,7 @@ template<std::size_t size, class T> class Vector {
* The computation is done in-place. @f[
* \boldsymbol a_i = -\boldsymbol a_i
* @f]
* @see Vector2::perpendicular()
*/
Vector<size, T> operator-() const {
Vector<size, T> out;

24
src/Math/Vector2.h

@ -80,6 +80,20 @@ template<class T> class Vector2: public Vector<2, T> {
*/
inline constexpr static Vector2<T> yScale(T scale) { return Vector2<T>(T(1), scale); }
/**
* @brief 2D cross product
*
* 2D version of cross product, equivalent to calling Vector3::cross()
* with Z coordinate set to `0` and extracting only Z coordinate from
* the result (X and Y coordinates are always zero).
* @f[
* \boldsymbol a \times \boldsymbol b = a_xb_y - a_yb_x
* @f]
*/
inline static T cross(const Vector2<T>& a, const Vector2<T>& b) {
return a.x()*b.y() - a.y()*b.x();
}
/** @copydoc Vector::Vector() */
inline constexpr /*implicit*/ Vector2() {}
@ -113,6 +127,16 @@ template<class T> class Vector2: public Vector<2, T> {
inline T& y() { return (*this)[1]; } /**< @brief Y component */
inline constexpr T y() const { return (*this)[1]; } /**< @overload */
/**
* @brief Perpendicular vector
*
* Returns vector rotated 90° counterclockwise. @f[
* \boldsymbol v_\perp = \begin{pmatrix} -v_y \\ v_x \end{pmatrix}
* @f]
* @see dot(const Vector&, const Vector&), operator-() const
*/
inline Vector2<T> perpendicular() const { return {-y(), x()}; }
MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector2, 2)
};

8
src/Math/Vector3.h

@ -102,12 +102,12 @@ template<class T> class Vector3: public Vector<3, T> {
* @brief Cross product
*
* @f[
* \boldsymbol a \times \boldsymbol b =
* \begin{pmatrix} c_0 \\ c_1 \\ c_2 \end{pmatrix} =
* \begin{pmatrix}a_1b_2 - a_2b_1 \\ a_2b_0 - a_0b_2 \\ a_0b_1 - a_1b_0 \end{pmatrix}
* \boldsymbol a \times \boldsymbol b =
* \begin{pmatrix}a_yb_z - a_zb_y \\ a_zb_y - a_xb_z \\ a_xb_y - a_yb_x \end{pmatrix}
* @f]
* @see Vector2::cross()
*/
inline constexpr static Vector3<T> cross(const Vector3<T>& a, const Vector3<T>& b) {
inline static Vector3<T> cross(const Vector3<T>& a, const Vector3<T>& b) {
return swizzle<'y', 'z', 'x'>(a)*swizzle<'z', 'x', 'y'>(b) -
swizzle<'z', 'x', 'y'>(a)*swizzle<'y', 'z', 'x'>(b);
}

6
src/Platform/AbstractXApplication.cpp

@ -50,7 +50,7 @@ void AbstractXApplication::createContext(AbstractXApplication::Configuration* co
viewportSize = configuration->size();
/* Get default X display */
display = XOpenDisplay(0);
display = XOpenDisplay(nullptr);
/* Get visual ID */
VisualID visualId = contextHandler->getVisualId(display);
@ -62,7 +62,7 @@ void AbstractXApplication::createContext(AbstractXApplication::Configuration* co
visInfo = XGetVisualInfo(display, VisualIDMask, &visTemplate, &visualCount);
if(!visInfo) {
Error() << "Cannot get X visual";
::exit(1);
std::exit(1);
}
/* Create X Window */
@ -74,7 +74,7 @@ void AbstractXApplication::createContext(AbstractXApplication::Configuration* co
attr.event_mask = 0;
unsigned long mask = CWBackPixel|CWBorderPixel|CWColormap|CWEventMask;
window = XCreateWindow(display, root, 20, 20, configuration->size().x(), configuration->size().y(), 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr);
XSetStandardProperties(display, window, configuration->title().c_str(), 0, None, 0, 0, 0);
XSetStandardProperties(display, window, configuration->title().c_str(), nullptr, None, nullptr, 0, nullptr);
XFree(visInfo);
/* Be notified about closing the window */

17
src/Platform/GlutApplication.cpp

@ -47,12 +47,20 @@ void GlutApplication::initialize(int& argc, char** argv) {
/* Init GLUT */
glutInit(&argc, argv);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
}
void GlutApplication::createContext(Configuration* configuration) {
CORRADE_ASSERT(!c, "GlutApplication::createContext(): context already created", );
if(!tryCreateContext(configuration)) {
Error() << "Platform::GlutApplication::createContext(): cannot create context";
delete configuration;
std::exit(1);
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
} else delete configuration;
}
bool GlutApplication::tryCreateContext(Configuration* configuration) {
CORRADE_ASSERT(!c, "Platform::GlutApplication::tryCreateContext(): context already created", false);
unsigned int flags = GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL;
@ -61,7 +69,8 @@ void GlutApplication::createContext(Configuration* configuration) {
glutInitDisplayMode(flags);
glutInitWindowSize(configuration->size().x(), configuration->size().y());
glutCreateWindow(configuration->title().c_str());
if(!glutCreateWindow(configuration->title().c_str()))
return false;
glutReshapeFunc(staticViewportEvent);
glutSpecialFunc(staticKeyEvent);
glutMouseFunc(staticMouseEvent);
@ -71,7 +80,7 @@ void GlutApplication::createContext(Configuration* configuration) {
ExtensionWrangler::initialize();
c = new Context;
delete configuration;
return true;
}
GlutApplication::~GlutApplication() {

19
src/Platform/GlutApplication.h

@ -81,7 +81,8 @@ class GlutApplication {
* @param arguments Application arguments
*
* Creates application with default configuration. See Configuration
* for more information.
* for more information. The program exits if the context cannot be
* created, see tryCreateContext() for an alternative.
*/
explicit GlutApplication(const Arguments& arguments);
@ -92,7 +93,8 @@ class GlutApplication {
*
* The @p configuration is deleted afterwards. If `nullptr` is passed
* as @p configuration, the context is not created and must be created
* with createContext().
* with createContext(). The program exits if the context cannot be
* created, see tryCreateContext() for an alternative.
*/
explicit GlutApplication(const Arguments& arguments, Configuration* configuration);
@ -112,10 +114,21 @@ class GlutApplication {
* @brief Create context with given configuration
*
* The @p configuration is deleted afterwards. Must be called if and
* only if the context wasn't created by the constructor itself.
* only if the context wasn't created by the constructor itself. The
* program exits if the context cannot be created, see tryCreateContext()
* for an alternative.
*/
void createContext(Configuration* configuration);
/**
* @brief Try to create context with given configuration
*
* Unlike createContext() the @p configuration is *not* deleted
* afterwards. Returns `false` if the context cannot be created, `true`
* otherwise.
*/
bool tryCreateContext(Configuration* configuration);
/** @{ @name Drawing functions */
/**

2
src/Platform/GlxContextHandler.cpp

@ -84,7 +84,7 @@ void GlxContextHandler::createContext(Window nativeWindow) {
/** @todo Use some extension wrangler for this, not GLEW, as it apparently needs context to create context, yo dawg wtf. */
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
context = glXCreateContextAttribsARB(display, configs[0], 0, True, attributes);
context = glXCreateContextAttribsARB(display, configs[0], nullptr, True, attributes);
XFree(configs);
if(!context) {
Error() << "GlxContextHandler: cannot create context.";

29
src/Platform/NaClApplication.cpp

@ -36,16 +36,25 @@ NaClApplication::NaClApplication(const Arguments& arguments): Instance(arguments
createContext(new Configuration);
}
NaClApplication::NaClApplication(const Arguments& arguments, Configuration* configuration): Instance(arguments), Graphics3DClient(this), MouseLock(this), c(nullptr) {
NaClApplication::NaClApplication(const Arguments& arguments, Configuration* configuration): Instance(arguments), Graphics3DClient(this), MouseLock(this), graphics(nullptr), fullscreen(nullptr), c(nullptr) {
if(configuration) createContext(configuration);
}
void NaClApplication::createContext(NaClApplication::Configuration* configuration) {
CORRADE_ASSERT(!c, "NaClApplication::createContext(): context already created", );
void NaClApplication::createContext(Configuration* configuration) {
if(!tryCreateContext(configuration)) {
Error() << "Platform::NaClApplication::createContext(): cannot create context";
delete configuration;
std::exit(1);
} else delete configuration;
}
bool NaClApplication::tryCreateContext(Configuration* configuration) {
CORRADE_ASSERT(!c, "Platform::NaClApplication::tryCreateContext(): context already created", false);
viewportSize = configuration->size();
std::int32_t attributes[] = {
const std::int32_t attributes[] = {
PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8,
@ -58,11 +67,12 @@ void NaClApplication::createContext(NaClApplication::Configuration* configuratio
graphics = new pp::Graphics3D(this, attributes);
if(graphics->is_null()) {
Error() << "Platform::NaClApplication::NaClApplication(): cannot create graphics";
std::exit(1);
delete graphics;
graphics = nullptr;
return false;
}
if(!BindGraphics(*graphics)) {
Error() << "Platform::NaClApplication::NaClApplication(): cannot bind graphics";
Error() << "Platform::NaClApplication::tryCreateContext(): cannot bind graphics";
std::exit(1);
}
@ -70,8 +80,6 @@ void NaClApplication::createContext(NaClApplication::Configuration* configuratio
glSetCurrentContextPPAPI(graphics->pp_resource());
c = new Context;
/* Enable input handling for mouse and keyboard */
RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE|PP_INPUTEVENT_CLASS_WHEEL);
RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
@ -79,7 +87,8 @@ void NaClApplication::createContext(NaClApplication::Configuration* configuratio
/* Make sure viewportEvent() is called for first time */
flags |= Flag::ViewportUpdated;
delete configuration;
c = new Context;
return true;
}
NaClApplication::~NaClApplication() {

3
src/Platform/NaClApplication.h

@ -121,6 +121,9 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public
/** @copydoc GlutApplication::createContext() */
void createContext(Configuration* configuration);
/** @copydoc GlutApplication::tryCreateContext() */
bool tryCreateContext(Configuration* configuration);
/** @{ @name Drawing functions */
/** @copydoc GlutApplication::viewportEvent() */

50
src/Platform/Sdl2Application.cpp

@ -50,39 +50,59 @@ Sdl2Application::InputEvent::Modifiers fixedModifiers(Uint16 mod) {
}
Sdl2Application::Sdl2Application(const Arguments&): context(nullptr), flags(Flag::Redraw) {
initialize();
createContext(new Configuration);
}
Sdl2Application::Sdl2Application(const Arguments&, Configuration* configuration): context(nullptr), flags(Flag::Redraw) {
initialize();
if(configuration) createContext(configuration);
}
void Sdl2Application::createContext(Configuration* configuration) {
CORRADE_ASSERT(!context, "Sdl2Application::createContext(): context already created", );
void Sdl2Application::initialize() {
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
Error() << "Cannot initialize SDL.";
std::exit(1);
}
}
void Sdl2Application::createContext(Configuration* configuration) {
if(!tryCreateContext(configuration)) {
Error() << "Platform::Sdl2Application::createContext(): cannot create context:" << SDL_GetError();
delete configuration;
std::exit(1);
} else delete configuration;
}
bool Sdl2Application::tryCreateContext(Configuration* configuration) {
CORRADE_ASSERT(!context, "Platform::Sdl2Application::tryCreateContext(): context already created", false);
/* Enable double buffering and 24bt depth buffer */
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
/* Multisampling */
if(configuration->sampleCount()) {
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, configuration->sampleCount());
}
window = SDL_CreateWindow(configuration->title().c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
configuration->size().x(), configuration->size().y(), SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if(!window) {
Error() << "Cannot create window.";
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, configuration->sampleCount() > 1 ? 1 : 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, configuration->sampleCount());
/* Flags: if not hidden, set as shown */
Uint32 flags(configuration->flags());
if(!(configuration->flags() & Configuration::Flag::Hidden)) flags |= SDL_WINDOW_SHOWN;
if(!(window = SDL_CreateWindow(configuration->title().c_str(),
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
configuration->size().x(), configuration->size().y(),
SDL_WINDOW_OPENGL|flags))) {
Error() << "Platform::Sdl2Application::tryCreateContext(): cannot create window";
std::exit(2);
}
context = SDL_GL_CreateContext(window);
if(!(context = SDL_GL_CreateContext(window))) {
SDL_DestroyWindow(window);
window = nullptr;
return false;
}
/* This must be enabled, otherwise (on my NVidia) it crashes when creating
VAO. WTF. */
@ -97,7 +117,7 @@ void Sdl2Application::createContext(Configuration* configuration) {
SDL_PushEvent(sizeEvent);
c = new Context;
delete configuration;
return true;
}
Sdl2Application::~Sdl2Application() {
@ -167,7 +187,7 @@ void Sdl2Application::setMouseLocked(bool enabled) {
SDL_SetRelativeMouseMode(enabled ? SDL_TRUE : SDL_FALSE);
}
Sdl2Application::Configuration::Configuration(): _title("Magnum SDL2 Application"), _size(800, 600), _sampleCount(0) {}
Sdl2Application::Configuration::Configuration(): _title("Magnum SDL2 Application"), _size(800, 600), _flags(Flag::Resizable), _sampleCount(0) {}
Sdl2Application::Configuration::~Configuration() = default;
Sdl2Application::InputEvent::Modifiers Sdl2Application::MouseEvent::modifiers() {

45
src/Platform/Sdl2Application.h

@ -95,6 +95,9 @@ class Sdl2Application {
/** @copydoc GlutApplication::createContext() */
void createContext(Configuration* configuration);
/** @copydoc GlutApplication::tryCreateContext() */
bool tryCreateContext(Configuration* configuration);
/** @{ @name Drawing functions */
/** @copydoc GlutApplication::viewportEvent() */
@ -167,6 +170,8 @@ class Sdl2Application {
typedef Corrade::Containers::EnumSet<Flag, UnsignedByte> Flags;
CORRADE_ENUMSET_FRIEND_OPERATORS(Flags)
void initialize();
SDL_Window* window;
SDL_GLContext context;
@ -191,6 +196,29 @@ class Sdl2Application::Configuration {
Configuration& operator=(Configuration&&) = delete;
public:
/**
* @brief Window flag
*
* @see Flags, setFlags()
*/
enum class Flag: Uint32 {
Resizable = SDL_WINDOW_RESIZABLE, /**< Resizable window */
Fullscreen = SDL_WINDOW_FULLSCREEN, /**< Fullscreen window */
Hidden = SDL_WINDOW_HIDDEN, /**< Hidden window */
Maximized = SDL_WINDOW_MAXIMIZED, /**< Maximized window */
Minimized = SDL_WINDOW_MINIMIZED, /**< Minimized window */
MouseLocked = SDL_WINDOW_INPUT_GRABBED /**< Window with mouse locked */
};
/**
* @brief Window flags
*
* @see setFlags()
*/
typedef Corrade::Containers::EnumSet<Flag, Uint32, SDL_WINDOW_RESIZABLE|
SDL_WINDOW_FULLSCREEN|SDL_WINDOW_HIDDEN|SDL_WINDOW_MAXIMIZED|
SDL_WINDOW_MINIMIZED|SDL_WINDOW_INPUT_GRABBED> Flags;
explicit Configuration();
~Configuration();
@ -222,6 +250,20 @@ class Sdl2Application::Configuration {
return this;
}
/** @brief Window flags */
inline Flags flags() const { return _flags; }
/**
* @brief Set window flags
* @return Pointer to self (for method chaining)
*
* Default is @ref Flag "Flag::Resizable".
*/
inline Configuration* setFlags(const Flags flags) {
_flags = flags;
return this;
}
/** @brief Sample count */
inline Int sampleCount() const { return _sampleCount; }
@ -240,9 +282,12 @@ class Sdl2Application::Configuration {
private:
std::string _title;
Vector2i _size;
Flags _flags;
Int _sampleCount;
};
CORRADE_ENUMSET_OPERATORS(Sdl2Application::Configuration::Flags)
/**
@brief Base for input events

2
src/Platform/WindowlessGlxApplication.cpp

@ -74,7 +74,7 @@ void WindowlessGlxApplication::createContext(Configuration* configuration) {
/** @todo Use some extension wrangler for this, not GLEW, as it apparently needs context to create context, yo dawg wtf. */
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
context = glXCreateContextAttribsARB(display, configs[0], 0, True, contextAttributes);
context = glXCreateContextAttribsARB(display, configs[0], nullptr, True, contextAttributes);
if(!context) {
Error() << "WindowlessGlxApplication: cannot create context.";
std::exit(1);

2
src/Primitives/CMakeLists.txt

@ -29,6 +29,7 @@ set(MagnumPrimitives_SRCS
Cube.cpp
Cylinder.cpp
Icosphere.cpp
Line.cpp
Plane.cpp
Square.cpp
UVSphere.cpp)
@ -40,6 +41,7 @@ set(MagnumPrimitives_HEADERS
Cube.h
Cylinder.h
Icosphere.h
Line.h
Plane.h
Square.h
UVSphere.h

45
src/Primitives/Line.cpp

@ -0,0 +1,45 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
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 "Line.h"
#include "Math/Vector3.h"
#include "Trade/MeshData2D.h"
#include "Trade/MeshData3D.h"
namespace Magnum { namespace Primitives {
Trade::MeshData2D Line2D::wireframe() {
return Trade::MeshData2D(Mesh::Primitive::Lines, nullptr, {new std::vector<Vector2>{
{0.0f, 0.0f}, {1.0f, 0.0f}
}}, {});
}
Trade::MeshData3D Line3D::wireframe() {
return Trade::MeshData3D(Mesh::Primitive::Lines, nullptr, {new std::vector<Vector3>{
{0.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f},
}}, {}, {});
}
}}

67
src/Primitives/Line.h

@ -0,0 +1,67 @@
#ifndef Magnum_Primitives_Line_h
#define Magnum_Primitives_Line_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
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.
*/
/** @file
* @brief Class Magnum::Primitives::Line2D, Magnum::Primitives::Line3D
*/
#include "Trade/Trade.h"
#include "Primitives/magnumPrimitivesVisibility.h"
namespace Magnum { namespace Primitives {
/**
@brief 2D line primitive
Unit-size line in direction of positive X axis. Non-indexed
@ref Mesh::Primitive "Lines".
*/
class MAGNUM_PRIMITIVES_EXPORT Line2D {
public:
/** @brief Wireframe line */
static Trade::MeshData2D wireframe();
Line2D() = delete;
};
/**
@brief 3D line primitive
Unit-size line in direction of positive X axis. Non-indexed
@ref Mesh::Primitive "Lines".
*/
class MAGNUM_PRIMITIVES_EXPORT Line3D {
public:
/** @brief Wireframe line */
static Trade::MeshData3D wireframe();
Line3D() = delete;
};
}}
#endif

18
src/SceneGraph/Object.hpp

@ -180,8 +180,6 @@ template<class Transformation> std::vector<typename Transformation::DataType> Ob
/* Remember object count for later */
std::size_t objectCount = objects.size();
/** @bug What if there is one objects twice in the list */
/* Mark all original objects as joints and create initial list of joints
from them */
for(std::size_t i = 0; i != objects.size(); ++i) {
@ -323,6 +321,22 @@ template<class Transformation> void Object<Transformation>::setClean(std::vector
/* No dirty objects left, done */
if(objects.empty()) return;
/* Add non-clean parents to the list. Mark each added object as visited, so
they aren't added more than once */
for(std::size_t end = objects.size(), i = 0; i != end; ++i) {
Object<Transformation>* o = objects[i];
o->flags |= Flag::Visited;
Object<Transformation>* parent = o->parent();
while(parent && !(parent->flags & Flag::Visited) && parent->isDirty()) {
objects.push_back(parent);
parent = parent->parent();
}
}
/* Cleanup all marks */
for(auto o: objects) o->flags &= ~Flag::Visited;
/* Compute absolute transformations */
Scene<Transformation>* scene = objects[0]->scene();
CORRADE_ASSERT(scene, "Object::setClean(): objects must be part of some scene", );

62
src/SceneGraph/Test/ObjectTest.cpp

@ -42,7 +42,8 @@ class ObjectTest: public Corrade::TestSuite::Tester {
void transformationsOrphan();
void transformationsDuplicate();
void setClean();
void bulkSetClean();
void setCleanListHierarchy();
void setCleanListBulk();
};
typedef SceneGraph::Object<SceneGraph::MatrixTransformation3D<>> Object3D;
@ -71,7 +72,8 @@ ObjectTest::ObjectTest() {
&ObjectTest::transformationsOrphan,
&ObjectTest::transformationsDuplicate,
&ObjectTest::setClean,
&ObjectTest::bulkSetClean});
&ObjectTest::setCleanListHierarchy,
&ObjectTest::setCleanListBulk});
}
void ObjectTest::parenting() {
@ -305,10 +307,13 @@ void ObjectTest::setClean() {
/* If the object itself is already clean, it shouldn't clean it again */
childOne->cleanedAbsoluteTransformation = Matrix4(Matrix4::Zero);
CORRADE_VERIFY(!childOne->isDirty());
childOne->setClean();
CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero));
/* If any object in the hierarchy is already clean, it shouldn't clean it again */
CORRADE_VERIFY(!childOne->isDirty());
CORRADE_VERIFY(childTwo->isDirty());
childTwo->setClean();
CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero));
@ -332,7 +337,58 @@ void ObjectTest::setClean() {
CORRADE_VERIFY(childThree->isDirty());
}
void ObjectTest::bulkSetClean() {
void ObjectTest::setCleanListHierarchy() {
Scene3D scene;
class CachingFeature: public AbstractFeature<3> {
public:
CachingFeature(AbstractObject<3>* object): AbstractFeature<3>(object) {
setCachedTransformations(CachedTransformation::Absolute);
}
Matrix4 cleanedAbsoluteTransformation;
void clean(const Matrix4& absoluteTransformation) override {
cleanedAbsoluteTransformation = absoluteTransformation;
}
};
CachingObject* childOne = new CachingObject(&scene);
childOne->scale(Vector3(2.0f));
CachingObject* childTwo = new CachingObject(childOne);
childTwo->translate(Vector3::xAxis(1.0f));
CachingFeature* childTwoFeature = new CachingFeature(childTwo);
CachingObject* childThree = new CachingObject(childTwo);
childThree->rotate(Deg(90.0f), Vector3::yAxis());
/* Clean the object and all its dirty parents (but not children) */
Scene3D::setClean(std::vector<Object3D*>{childTwo});
CORRADE_VERIFY(!scene.isDirty());
CORRADE_VERIFY(!childOne->isDirty());
CORRADE_VERIFY(!childTwo->isDirty());
CORRADE_VERIFY(childThree->isDirty());
/* Verify the right matrices were passed */
CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, childOne->absoluteTransformationMatrix());
CORRADE_COMPARE(childTwo->cleanedAbsoluteTransformation, childTwo->absoluteTransformationMatrix());
CORRADE_COMPARE(childTwoFeature->cleanedAbsoluteTransformation, childTwo->absoluteTransformationMatrix());
/* If the object itself is already clean, it shouldn't clean it again */
childOne->cleanedAbsoluteTransformation = Matrix4(Matrix4::Zero);
CORRADE_VERIFY(!childOne->isDirty());
Scene3D::setClean(std::vector<Object3D*>{childOne});
CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero));
/* If any object in the hierarchy is already clean, it shouldn't clean it again */
CORRADE_VERIFY(!childOne->isDirty());
childTwo->setDirty();
Scene3D::setClean(std::vector<Object3D*>{childTwo});
CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero));
}
void ObjectTest::setCleanListBulk() {
/* Verify it doesn't crash when passed empty list */
Object3D::setClean(std::vector<Object3D*>());

5
src/Timeline.h

@ -58,10 +58,9 @@ performed, after everything is properly initialized.
In your draw event implementation don't forget to call nextFrame() after
buffer swap. You can use previousFrameDuration() to compute animation speed.
Example usage (in e.g. @ref Platform::GlutApplication "GlutApplication"
subclass):
Example usage:
@code
MyApplication::MyApplication(...): Platform::GlutApplication(...) {
MyApplication::MyApplication(const Parameters& parameters): Platform::Application(parameters) {
// Initialization ...
timeline.setMinimalFrameTime(1/120.0f); // 120 FPS at max

Loading…
Cancel
Save