Skip to content

Commit

Permalink
New example showcasing usage with Box2D.
Browse files Browse the repository at this point in the history
  • Loading branch information
mosra committed Aug 24, 2018
1 parent ff60dec commit 62d4712
Show file tree
Hide file tree
Showing 6 changed files with 328 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ find_package(Magnum REQUIRED)
include(CMakeDependentOption)
option(WITH_AREALIGHTS_EXAMPLE "Build arealights example" OFF)
option(WITH_AUDIO_EXAMPLE "Build audio example (requires Magnum Audio library)" OFF)
option(WITH_BOX2D_EXAMPLE "Build Box2D integration example" OFF)
option(WITH_BULLET_EXAMPLE "Build Bullet integration example (requires BulletIntegration library)" OFF)
cmake_dependent_option(WITH_CUBEMAP_EXAMPLE "Build CubeMap example (requires JpegImporter plugin)" OFF "NOT MAGNUM_TARGET_GLES" OFF)
option(WITH_LEAPMOTION_EXAMPLE "Build LeapMotion example" OFF)
Expand Down
3 changes: 3 additions & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Third-party components
- The sound file used is a Chimes Sound Effect from
http://www.orangefreesounds.com/chimes-sound-effect/, licensed under
a [Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/).
- The Box2D example uses the [Box2D](https://box2d.org/) library, licensed
under the [zlib license](https://github.com/erincatto/Box2D/blob/master/LICENSE)
- The sokol_gfx Triangle example uses the [sokol_gfx](https://github.com/floooh/sokol)
library by Andre Weissflog, licensed under the
[zlib/libpng license](https://github.com/floooh/sokol/blob/master/LICENSE).
Expand All @@ -24,6 +26,7 @@ Contributors to Magnum examples
- Bill Robinson ([@wivlaro](https://github.com/wivlaro) -- Shadows example
- Olga Turanksaya ([@olga-python](https://github.com/olga-python)) -- Gentoo
ebuild
- Michal Mikula -- Box2D example
- Nathan Ollerenshaw ([@matjam](https://github.com/matjam)) --- Ubuntu
package updates, a PPA repository for stable versions

Expand Down
62 changes: 62 additions & 0 deletions modules/FindBox2D.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#.rst:
# Find Box2D
# ----------
#
# Finds the Box2D library. This module defines:
#
# Box2D_FOUND - True if Box2D library is found
# Box2D::Box2D - Box2D imported target
#
# Additionally these variables are defined for internal usage:
#
# BOX2D_LIBRARY - Box2D library
# BOX2D_INCLUDE_DIR - Include dir
#

#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
# 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.
#

# Library
find_library(BOX2D_LIBRARY NAMES Box2D)

# Include dir
find_path(BOX2D_INCLUDE_DIR
NAMES Box2D/Box2D.h)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Box2D DEFAULT_MSG
BOX2D_LIBRARY
BOX2D_INCLUDE_DIR)

mark_as_advanced(FORCE
BOX2D_LIBRARY
BOX2D_INCLUDE_DIR)

if(NOT TARGET Box2D::Box2D)
add_library(Box2D::Box2D UNKNOWN IMPORTED)
set_target_properties(Box2D::Box2D PROPERTIES
IMPORTED_LOCATION ${BOX2D_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${BOX2D_INCLUDE_DIR})
endif()
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ if(WITH_AUDIO_EXAMPLE)
add_subdirectory(audio)
endif()

if(WITH_BOX2D_EXAMPLE)
add_subdirectory(box2d)
endif()

if(WITH_BULLET_EXAMPLE)
add_subdirectory(bullet)
endif()
Expand Down
176 changes: 176 additions & 0 deletions src/box2d/Box2DExample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/*
This file is part of Magnum.
Original authors — credit is appreciated but not required:
2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 —
Vladimír Vondruš <mosra@centrum.cz>
2018 — Michal Mikula <miso.mikula@gmail.com>
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute
this software, either in source code form or as a compiled binary, for any
purpose, commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of
this software dedicate any and all copyright interest in the software to
the public domain. We make this dedication for the benefit of the public
at large and to the detriment of our heirs and successors. We intend this
dedication to be an overt act of relinquishment in perpetuity of all
present and future rights to this software under copyright law.
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 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 <Box2D/Box2D.h>
#include <Magnum/GL/Context.h>
#include <Magnum/GL/DefaultFramebuffer.h>
#include <Magnum/GL/Buffer.h>
#include <Magnum/GL/Mesh.h>
#include <Magnum/MeshTools/Compile.h>
#include <Magnum/Platform/Sdl2Application.h>
#include <Magnum/Primitives/Square.h>
#include <Magnum/SceneGraph/Camera.h>
#include <Magnum/SceneGraph/Drawable.h>
#include <Magnum/SceneGraph/TranslationRotationScalingTransformation2D.h>
#include <Magnum/SceneGraph/Scene.h>
#include <Magnum/Shaders/Flat.h>
#include <Magnum/Trade/MeshData2D.h>

namespace Magnum { namespace Examples {

typedef SceneGraph::Object<SceneGraph::TranslationRotationScalingTransformation2D> Object2D;
typedef SceneGraph::Scene<SceneGraph::TranslationRotationScalingTransformation2D> Scene2D;

using namespace Math::Literals;

class Box2DExample: public Platform::Application {
public:
explicit Box2DExample(const Arguments& arguments);

private:
void drawEvent() override;
void mousePressEvent(MouseEvent& event) override;

b2Body* createBody(Object2D& object, const Vector2& size, b2BodyType type, const Vector2& position, Float density = 1.0f);

GL::Mesh _mesh;
Shaders::Flat2D _shader;

Scene2D _scene;
Object2D* _cameraObject;
SceneGraph::Camera2D* _camera;
SceneGraph::DrawableGroup2D _drawables;
Containers::Optional<b2World> _world;
};

class BoxDrawable: public SceneGraph::Drawable2D {
public:
explicit BoxDrawable(Object2D& object, GL::Mesh& mesh, Shaders::Flat2D& shader, const Color4& color, SceneGraph::DrawableGroup2D& drawables): SceneGraph::Drawable2D{object, &drawables}, _mesh(mesh), _shader(shader), _color{color} {}

private:
void draw(const Matrix3& transformationMatrix, SceneGraph::Camera2D& camera) override {
_shader
.setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix)
.setColor(_color);
_mesh.draw(_shader);
}

GL::Mesh& _mesh;
Shaders::Flat2D& _shader;
Color4 _color;
};

b2Body* Box2DExample::createBody(Object2D& object, const Vector2& halfSize, const b2BodyType type, const Vector2& position, const Float density) {
b2BodyDef bodyDefinition;
bodyDefinition.position.Set(position.x(), position.y());
bodyDefinition.type = type;
b2Body* body = _world->CreateBody(&bodyDefinition);

b2PolygonShape shape;
shape.SetAsBox(halfSize.x(), halfSize.y());

b2FixtureDef fixture;
fixture.friction = 0.8f;
fixture.density = density;
fixture.shape = &shape;
body->CreateFixture(&fixture);

body->SetUserData(&object);
object.setScaling(halfSize);

return body;
}

Box2DExample::Box2DExample(const Arguments& arguments):
Platform::Application{arguments, Configuration{}.setTitle("Magnum Box2D Example")}
{
/* Configure camera */
_cameraObject = new Object2D{&_scene};
_camera = new SceneGraph::Camera2D{*_cameraObject};
_camera->setAspectRatioPolicy(SceneGraph::AspectRatioPolicy::Extend)
.setProjectionMatrix(Matrix3::projection({20.0f, 20.0f}))
.setViewport(GL::defaultFramebuffer.viewport().size());

/* Create the Box2D world with the usual gravity vector */
_world.emplace(b2Vec2{0.0f, -9.81f});

/* Create the box mesh */
_mesh = MeshTools::compile(Primitives::squareSolid());

/* Create the ground */
auto ground = new Object2D{&_scene};
createBody(*ground, {11.0f, 0.5f}, b2_staticBody, Vector2::yAxis(-8.0f));
new BoxDrawable{*ground, _mesh, _shader, 0xa5c9ea_rgbf, _drawables};

/* Create a pyramid of boxes */
for(std::size_t row = 0; row != 15; ++row) {
for(std::size_t item = 0; item != 15 - row; ++item) {
auto box = new Object2D{&_scene};
createBody(*box, {0.5f, 0.5f}, b2_dynamicBody,
{Float(row)*0.6f + Float(item)*1.2f - 8.5f, Float(row)*1.0f - 6.0f});
new BoxDrawable{*box, _mesh, _shader, 0x2f83cc_rgbf, _drawables};
}
}

setSwapInterval(1);
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_ANDROID)
setMinimalLoopPeriod(16);
#endif
}

void Box2DExample::mousePressEvent(MouseEvent& event) {
/* Calculate mouse position in the Box2D world. Make it relative to window,
with origin at center and then scale to world size with Y inverted. */
const auto position = _camera->projectionSize()*Vector2::yScale(-1.0f)*(Vector2{event.position()}/Vector2{windowSize()} - Vector2{0.5f});

auto destroyer = new Object2D{&_scene};
createBody(*destroyer, {0.5f, 0.5f}, b2_dynamicBody, position, 2.0f);
new BoxDrawable{*destroyer, _mesh, _shader, 0xffff66_rgbf, _drawables};
}

void Box2DExample::drawEvent() {
GL::defaultFramebuffer.clear(GL::FramebufferClear::Color);

/* Step the world and update all object positions */
_world->Step(1.0f/60.0f, 6, 2);
for(b2Body* body = _world->GetBodyList(); body; body = body->GetNext())
(*static_cast<Object2D*>(body->GetUserData()))
.setTranslation({body->GetPosition().x, body->GetPosition().y})
.setRotation(Complex::rotation(Rad(body->GetAngle())));

_camera->draw(_drawables);

swapBuffers();
redraw();
}

}}

MAGNUM_APPLICATION_MAIN(Magnum::Examples::Box2DExample)
82 changes: 82 additions & 0 deletions src/box2d/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#
# This file is part of Magnum.
#
# Original authors — credit is appreciated but not required:
#
# 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 —
# Vladimír Vondruš <mosra@centrum.cz>
# 2018 — Michal Mikula <miso.mikula@gmail.com>
#
# This is free and unencumbered software released into the public domain.
#
# Anyone is free to copy, modify, publish, use, compile, sell, or distribute
# this software, either in source code form or as a compiled binary, for any
# purpose, commercial or non-commercial, and by any means.
#
# In jurisdictions that recognize copyright laws, the author or authors of
# this software dedicate any and all copyright interest in the software to
# the public domain. We make this dedication for the benefit of the public
# at large and to the detriment of our heirs and successors. We intend this
# dedication to be an overt act of relinquishment in perpetuity of all
# present and future rights to this software under copyright law.
#
# 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 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.
#

cmake_minimum_required(VERSION 2.8.12)

# CMake policies. 0025 needs to be before project(), so putting all there.
# Use AppleClang instead of Clang on Apple
if(POLICY CMP0025)
cmake_policy(SET CMP0025 NEW)
endif()
# Don't treat imported targets with :: as files
if(POLICY CMP0028)
cmake_policy(SET CMP0028 NEW)
endif()
# Enable MACOSX_RPATH by default
if(POLICY CMP0042)
cmake_policy(SET CMP0042 NEW)
endif()
# Quoted variables should not be dereferenced
if(POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()

project(MagnumBox2DExample)

# Add module path in case this is project root
if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/../../modules/")
endif()

find_package(Magnum REQUIRED
GL
MeshTools
Primitives
SceneGraph
Sdl2Application
Shaders
Trade)
find_package(Box2D REQUIRED)

set_directory_properties(PROPERTIES CORRADE_USE_PEDANTIC_FLAGS ON)

add_executable(magnum-box2d Box2DExample.cpp)
target_link_libraries(magnum-box2d PRIVATE
Magnum::Application
Magnum::GL
Magnum::Magnum
Magnum::MeshTools
Magnum::Primitives
Magnum::SceneGraph
Magnum::Shaders
Magnum::Trade
Box2D::Box2D)

install(TARGETS magnum-box2d DESTINATION ${MAGNUM_BINARY_INSTALL_DIR})

0 comments on commit 62d4712

Please sign in to comment.