From f5b5a7e216b7467aa86022f53454ab8d9485a11f Mon Sep 17 00:00:00 2001 From: Squareys Date: Tue, 17 Nov 2015 23:21:46 +0100 Subject: [PATCH 01/10] octree: Initial skeleton for future octree example. Signed-off-by: Squareys --- CMakeLists.txt | 1 + src/CMakeLists.txt | 4 ++ src/octree/CMakeLists.txt | 60 +++++++++++++++++++ src/octree/OctreeExample.cpp | 110 +++++++++++++++++++++++++++++++++++ src/octree/README.md | 2 + 5 files changed, 177 insertions(+) create mode 100644 src/octree/CMakeLists.txt create mode 100644 src/octree/OctreeExample.cpp create mode 100644 src/octree/README.md diff --git a/CMakeLists.txt b/CMakeLists.txt index d1b4ec83b..e027c7551 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,7 @@ option(WITH_AUDIO_EXAMPLE "Build audio example (requires Magnum Audio library)" 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) cmake_dependent_option(WITH_MOTIONBLUR_EXAMPLE "Build MotionBlur example" OFF "NOT MAGNUM_TARGET_GLES" OFF) +option(WITH_OCTREE_EXAMPLE "Build Octree: example" OFF) option(WITH_OVR_EXAMPLE "Build OVR example" OFF) option(WITH_PICKING_EXAMPLE "Build Picking example" OFF) option(WITH_PRIMITIVES_EXAMPLE "Build Primitives example" OFF) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 21db93b44..9549f8afc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -58,6 +58,10 @@ if(WITH_MOTIONBLUR_EXAMPLE) add_subdirectory(motionblur) endif() +if(WITH_OCTREE_EXAMPLE) + add_subdirectory(octree) +endif() + if(WITH_OVR_EXAMPLE) add_subdirectory(ovr) endif() diff --git a/src/octree/CMakeLists.txt b/src/octree/CMakeLists.txt new file mode 100644 index 000000000..8aed5d704 --- /dev/null +++ b/src/octree/CMakeLists.txt @@ -0,0 +1,60 @@ +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013, 2014, 2015 +# Vladimír Vondruš +# Copyright © 2015 Jonathan Hale +# +# 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. +# + +cmake_minimum_required(VERSION 2.8.9) +project(MagnumOctreeExample) + +# CMake policies: enable MACOSX_RPATH by default +if(POLICY CMP0042) + cmake_policy(SET CMP0042 NEW) +endif() +# Don't treat imported targets with :: as files +if(POLICY CMP0028) + cmake_policy(SET CMP0028 NEW) +endif() + +find_package(Magnum REQUIRED + DebugTools + SceneGraph + Sdl2Application) + +find_package(MagnumExtras REQUIRED + Octree + SceneGraph) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CORRADE_CXX_FLAGS}") +include_directories(${MAGNUM_INCLUDE_DIRS} ${MAGNUM_OCTREE_INCLUDE_DIRS} ${MAGNUM_APPLICATION_INCLUDE_DIRS}) + +add_executable(magnum-octree OctreeExample.cpp) +target_link_libraries(magnum-octree + ${MAGNUM_LIBRARIES} + ${MAGNUM_DEBUGTOOLS_LIBRARIES} + ${MAGNUMEXTRAS_SCENEGRAPH_LIBRARIES} + ${MAGNUMEXTRAS_OCTREE_LIBRARIES} + ${MAGNUM_APPLICATION_LIBRARIES}) + +install(TARGETS magnum-octree DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}) +install(FILES README.md DESTINATION ${MAGNUM_DATA_INSTALL_DIR}/examples RENAME README-octree.md) diff --git a/src/octree/OctreeExample.cpp b/src/octree/OctreeExample.cpp new file mode 100644 index 000000000..752aca45b --- /dev/null +++ b/src/octree/OctreeExample.cpp @@ -0,0 +1,110 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015 + Vladimír Vondruš + Copyright © 2015 Andrea Capobianco + Copyright © 2015 Jonathan Hale + + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace Magnum { namespace Examples { + +using namespace SceneGraph; +using namespace DebugTools; + +typedef Scene Scene3D; +typedef Object Object3D; + +class OctreeExample: public Platform::Application { + public: + explicit OctreeExample(const Arguments& arguments); + + private: + void drawEvent() override; + void addBox(Shapes::AxisAlignedBox3D& box); + + DebugTools::ResourceManager _manager; + + Scene3D _scene; + Camera3D _camera; /* camera which will be culled for */ + Camera3D _viewer; /* camera from which we will render */ + + OctreeDrawableGroup _drawables; + ShapeGroup<3> _shapes; +}; + +OctreeExample::OctreeExample(const Arguments& arguments): + Platform::Application{arguments, Configuration{}.setTitle("Magnum Octree View Frustrum Culling Example")}, + _camera(_scene), + _viewer(_scene) +{ + Renderer::enable(Renderer::Feature::DepthTest); + + _camera.setProjectionMatrix(Matrix4::perspectiveProjection(75.0_degf, Vector2{defaultFramebuffer.viewport().size()}.aspectRatio(), 0.01f, 100.0f)); + + // TODO: Add more colors + _manager.set("pink", DebugTools::ShapeRendererOptions().setColor({1.0f, 0.0f, 1.0f})); + + // TODO: Setup _camera and _viewer transformation + + // TODO: add more boxes + auto shape = Shapes::AxisAlignedBox3D(Vector3{-0.5}, Vector3{0.5}); + addBox(shape); +} + +void OctreeExample::addBox(Shapes::AxisAlignedBox3D& box) { + Shapes::Shape* theShape = new Shapes::Shape(*(new Object3D(&_scene)), box, &_shapes); + + // TODO: maybe randomize the color? *later* + ShapeRenderer<3>* renderer = new ShapeRenderer<3>(*theShape, ResourceKey("pink")); + + _drawables.add(*renderer, box); +} + +void OctreeExample::drawEvent() { + defaultFramebuffer.clear(FramebufferClear::Color | FramebufferClear::Depth); + + // TODO: cull for _camera + + _viewer.draw(_drawables); + + swapBuffers(); +} + +}} + +MAGNUM_APPLICATION_MAIN(Magnum::Examples::OctreeExample) diff --git a/src/octree/README.md b/src/octree/README.md new file mode 100644 index 000000000..7cac2ec05 --- /dev/null +++ b/src/octree/README.md @@ -0,0 +1,2 @@ +This example shows how to use octree view frustum culling in magnum. +![Octree](octree.png) From 566cf33a8066c202b3a7faa3aa44dafccbc1b8dc Mon Sep 17 00:00:00 2001 From: ACapo93 Date: Mon, 7 Dec 2015 20:31:53 +0100 Subject: [PATCH 02/10] octree: Implement octree example. still shows some unexpected behaviour under certain circumstances. --- src/octree/OctreeExample.cpp | 138 +++++++++++++++++++++++++++++++---- 1 file changed, 124 insertions(+), 14 deletions(-) diff --git a/src/octree/OctreeExample.cpp b/src/octree/OctreeExample.cpp index 752aca45b..83320821c 100644 --- a/src/octree/OctreeExample.cpp +++ b/src/octree/OctreeExample.cpp @@ -38,7 +38,11 @@ #include #include #include +#include #include +#include +#include +#include namespace Magnum { namespace Examples { @@ -49,6 +53,21 @@ using namespace DebugTools; typedef Scene Scene3D; typedef Object Object3D; +class FrustumDrawable: public Object3D, public SceneGraph::Drawable3D { + public: + explicit FrustumDrawable(Object3D* parent, SceneGraph::DrawableGroup3D* group, Mesh& mesh): Object3D{parent}, SceneGraph::Drawable3D{*this, group}, _mesh(mesh) { + } + private: + void draw(const Matrix4& transformationMatrix, Camera3D& camera) override { + /* The scaling in the TransformationProjectionMatrix for reflection, because of use of DirectX matrices instead of OpenGL ones */ + _shader.setColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f)) + .setTransformationProjectionMatrix(camera.projectionMatrix() * transformationMatrix * Matrix4::scaling(Vector3{1, 1, -1})); + _mesh.draw(_shader); + } + Mesh& _mesh; + Shaders::Flat3D _shader; +}; + class OctreeExample: public Platform::Application { public: explicit OctreeExample(const Arguments& arguments); @@ -56,53 +75,144 @@ class OctreeExample: public Platform::Application { private: void drawEvent() override; void addBox(Shapes::AxisAlignedBox3D& box); + Vector3 calculateIntersection(const Vector4& v1, const Vector4& v2, const Vector4& v3); DebugTools::ResourceManager _manager; Scene3D _scene; + Object3D _cameraObject; + Object3D _viewerObject; Camera3D _camera; /* camera which will be culled for */ Camera3D _viewer; /* camera from which we will render */ - OctreeDrawableGroup _drawables; + OctreeDrawableGroup _culledDrawables; ShapeGroup<3> _shapes; + + DrawableGroup3D _drawables; + + Buffer _buffer; + Mesh _mesh; + }; OctreeExample::OctreeExample(const Arguments& arguments): Platform::Application{arguments, Configuration{}.setTitle("Magnum Octree View Frustrum Culling Example")}, - _camera(_scene), - _viewer(_scene) + _cameraObject(&_scene), + _viewerObject(&_scene), + _camera(_cameraObject), + _viewer(_viewerObject) { Renderer::enable(Renderer::Feature::DepthTest); - _camera.setProjectionMatrix(Matrix4::perspectiveProjection(75.0_degf, Vector2{defaultFramebuffer.viewport().size()}.aspectRatio(), 0.01f, 100.0f)); + _camera.setProjectionMatrix(Matrix4::perspectiveProjection(75.0_degf, Vector2{defaultFramebuffer.viewport().size()}.aspectRatio(), 0.01f, 75.0f)); + _viewer.setProjectionMatrix(Matrix4::perspectiveProjection(75.0_degf, Vector2{defaultFramebuffer.viewport().size()}.aspectRatio(), 0.01f, 150.0f)); - // TODO: Add more colors _manager.set("pink", DebugTools::ShapeRendererOptions().setColor({1.0f, 0.0f, 1.0f})); - // TODO: Setup _camera and _viewer transformation + //Setup _camera and _viewer transformation + _viewerObject.translate({0.0f, 10.0f, 50.0f}); + _viewerObject.rotateXLocal(Deg(-10.0f)); + + //create visualisation of _camera view frustum + const Matrix4 projection = Matrix4(_camera.projectionMatrix()).transposed(); + const Vector4 left{projection[3] + projection[0]}; + const Vector4 right{projection[3] - projection[0]}; + const Vector4 bottom{projection[3] + projection[1]}; + const Vector4 top{projection[3] - projection[1]}; + const Vector4 near{projection[2]}; + const Vector4 far{projection[3] - projection[2]}; + + const Vector3 rbn = calculateIntersection(right, bottom, near); + const Vector3 lbn = calculateIntersection(left, bottom, near); + const Vector3 rtn = calculateIntersection(right, top, near); + const Vector3 ltn = calculateIntersection(left, top, near); + const Vector3 rbf = calculateIntersection(right, bottom, far); + const Vector3 lbf = calculateIntersection(left, bottom, far); + const Vector3 rtf = calculateIntersection(right, top, far); + const Vector3 ltf = calculateIntersection(left, top, far); + + const Vector3 data[] = { + rbn, lbn, ltn, rtn, + rbn, rbf, rtf, rtn, + rtf, ltf, ltn, ltf, + lbf, lbn, lbf, rbf + }; + + _buffer.setData(data, BufferUsage::StaticDraw); + _mesh.setPrimitive(MeshPrimitive::LineStrip) + .setCount(16) + .addVertexBuffer(_buffer, 0, Shaders::Flat3D::Position{}); + + new FrustumDrawable(&_cameraObject, &_drawables, _mesh); // TODO: add more boxes - auto shape = Shapes::AxisAlignedBox3D(Vector3{-0.5}, Vector3{0.5}); - addBox(shape); + // TODO: Do it with a loop and random values + auto rightBox = Shapes::AxisAlignedBox3D(Vector3{10.0, -0.5, -0.5}, Vector3{11.0, 0.5, 0.5}); + //doesn't break the culling + //auto rightBox = Shapes::AxisAlignedBox3D(Vector3{10.0, -0.5, -10.5}, Vector3{11.0, 0.5, 0.5}); + //breaks the culling + //auto rightBox = Shapes::AxisAlignedBox3D(Vector3{10.0, -0.5, -15.5}, Vector3{11.0, 0.5, 0.5}); + addBox(rightBox); + + auto leftBox = Shapes::AxisAlignedBox3D(Vector3{-11.0, -0.5, -0.5}, Vector3{-10.0, 0.5, 0.5}); + addBox(leftBox); + + auto nearBox = Shapes::AxisAlignedBox3D(Vector3{-0.5, -0.5, 10.0}, Vector3{0.5, 0.5, 11.0}); + addBox(nearBox); + + auto farBox = Shapes::AxisAlignedBox3D(Vector3{-0.5, -0.5, -11.0}, Vector3{0.5, 0.5, -10.0}); + addBox(farBox); + + auto originBox = Shapes::AxisAlignedBox3D(Vector3{-0.5}, Vector3{0.5}); + addBox(originBox); + + //breaks the culling + //auto shape5 = Shapes::AxisAlignedBox3D(Vector3{-25.5, 5.5, -46.5}, Vector3{-24.5, 6.5, -45.5}); + //addBox(shape5); + +} + +Vector3 OctreeExample::calculateIntersection(const Vector4 &v1, const Vector4 &v2, const Vector4 &v3) { + + const Float det = Matrix3(v1.xyz(), v2.xyz(), v3.xyz()).transposed().determinant(); + + const Float x = Matrix3({v1.w(), v2.w(), v3.w()}, {v1.y(), v2.y(), v3.y()}, {v1.z(), v2.z(), v3.z()}).determinant() / det; + const Float y = Matrix3({v1.x(), v2.x(), v3.x()}, {v1.w(), v2.w(), v3.w()}, {v1.z(), v2.z(), v3.z()}).determinant() / det; + const Float z = Matrix3({v1.x(), v2.x(), v3.x()}, {v1.y(), v2.y(), v3.y()}, {v1.w(), v2.w(), v3.w()}).determinant() / det; + + return Vector3{x, y, z}; } -void OctreeExample::addBox(Shapes::AxisAlignedBox3D& box) { - Shapes::Shape* theShape = new Shapes::Shape(*(new Object3D(&_scene)), box, &_shapes); +void OctreeExample::addBox(Shapes::AxisAlignedBox3D& aabox) { + + const Vector3 s = aabox.max() - aabox.min(); + const Vector3 t = aabox.min() + s/2; + const Matrix4 transformationMatrix = Matrix4::translation(t) * Matrix4::scaling(s); + + Shapes::Shape* box = new Shapes::Shape(_scene, transformationMatrix, &_shapes); + new DebugTools::ShapeRenderer3D(*box, ResourceKey("pink"), &_culledDrawables); // TODO: maybe randomize the color? *later* - ShapeRenderer<3>* renderer = new ShapeRenderer<3>(*theShape, ResourceKey("pink")); + ShapeRenderer<3>* renderer = new ShapeRenderer<3>(*box, ResourceKey("pink")); - _drawables.add(*renderer, box); + _culledDrawables.add(*renderer, aabox); } void OctreeExample::drawEvent() { defaultFramebuffer.clear(FramebufferClear::Color | FramebufferClear::Depth); - // TODO: cull for _camera + // cull for _camera + _culledDrawables.buildOctree(); + _culledDrawables.cull(_camera); + _viewer.draw(_culledDrawables); _viewer.draw(_drawables); - swapBuffers(); + + // rotate _camera to change cull result + _cameraObject.rotateYLocal(Deg(0.5f)); + + redraw(); } }} From 7fe83da40b0e6f2ec4db0ef61f40b53c8a9b3539 Mon Sep 17 00:00:00 2001 From: Squareys Date: Sun, 11 Sep 2016 22:12:26 +0200 Subject: [PATCH 03/10] Octree: Fix octree example and add S key to switch views Signed-off-by: Squareys --- modules/FindMagnumExtras.cmake | 210 +++++++++++++++++++++++++++++++++ src/octree/OctreeExample.cpp | 110 +++++++++-------- 2 files changed, 270 insertions(+), 50 deletions(-) create mode 100644 modules/FindMagnumExtras.cmake diff --git a/modules/FindMagnumExtras.cmake b/modules/FindMagnumExtras.cmake new file mode 100644 index 000000000..838850b71 --- /dev/null +++ b/modules/FindMagnumExtras.cmake @@ -0,0 +1,210 @@ +#.rst: +# Find Magnum extras +# ------------------ +# +# Finds Magnum extras. Basic usage:: +# +# find_package(MagnumExtras REQUIRED) +# +# This command tries to find Magnum extras and then defines the following: +# +# MagnumExtras_FOUND - Whether Magnum extras were found +# +# This command alone is useless without specifying the components: +# +# Octree - Octree BSP structure for Magnum::SceneGraph +# +# Example usage with specifying additional components is: +# +# find_package(MagnumExtras REQUIRED SomeLibraryThatDoesntExistYet) +# +# For each component is then defined: +# +# MagnumExtras_*_FOUND - Whether the component was found +# MagnumExtras::* - Component imported target +# +# The package is found if either debug or release version of each requested +# library is found. If both debug and release libraries are found, proper +# version is chosen based on actual build configuration of the project (i.e. +# Debug build is linked to debug libraries, Release build to release +# libraries). +# +# Additionally these variables are defined for internal usage: +# +# MAGNUMEXTRAS_INCLUDE_DIR - Magnum extras include dir (w/o +# dependencies) +# MAGNUMEXTRAS_*_LIBRARY_DEBUG - Debug version of given library, if found +# MAGNUMEXTRAS_*_LIBRARY_RELEASE - Release version of given library, if +# found +# + +# +# This file is part of Magnum. +# +# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 +# Vladimír Vondruš +# Copyright © 2016 Jonathan Hale +# +# 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. +# + +# Corrade library dependencies +set(_MAGNUMEXTRAS_CORRADE_DEPENDENCIES ) + +foreach(_component ${MagnumExtras_FIND_COMPONENTS}) + string(TOUPPER ${_component} _COMPONENT) + + # (none yet) + + list(APPEND _MAGNUMEXTRAS_CORRADE_DEPENDENCIES ${_MAGNUMEXTRAS_${_COMPONENT}_CORRADE_DEPENDENCIES}) +endforeach() +find_package(Corrade REQUIRED ${_MAGNUMEXTRAS_CORRADE_DEPENDENCIES}) + +# Magnum library dependencies +set(_MAGNUMEXTRAS_MAGNUM_DEPENDENCIES ) +foreach(_component ${MagnumExtras_FIND_COMPONENTS}) + string(TOUPPER ${_component} _COMPONENT) + + if(_component MATCHES Octree) + set(_MAGNUMEXTRAS_${_COMPONENT}_MAGNUM_DEPENDENCIES Shapes) + endif() + + if(_component MATCHES SceneGraph) + set(_MAGNUMEXTRAS_${_COMPONENT}_MAGNUM_DEPENDENCIES SceneGraph) + endif() + + list(APPEND _MAGNUMEXTRAS_MAGNUM_DEPENDENCIES ${_MAGNUMEXTRAS_${_COMPONENT}_MAGNUM_DEPENDENCIES}) +endforeach() +find_package(Magnum REQUIRED ${_MAGNUMEXTRAS_MAGNUM_DEPENDENCIES}) + +# Global integration include dir +find_path(MAGNUMEXTRAS_INCLUDE_DIR Magnum + HINTS ${MAGNUM_INCLUDE_DIR}) +mark_as_advanced(MAGNUMEXTRAS_INCLUDE_DIR) + +# Ensure that all inter-component dependencies are specified as well +set(_MAGNUMEXTRAS_ADDITIONAL_COMPONENTS ) +foreach(_component ${MagnumExtras_FIND_COMPONENTS}) + string(TOUPPER ${_component} _COMPONENT) + + # (no inter-component dependencies yet) + if(_component MATCHES SceneGraph) + set(_MAGNUMEXTRAS_${_COMPONENT}_DEPENDENCIES Octree) + endif() + + # Mark the dependencies as required if the component is also required + if(MagnumExtras_FIND_REQUIRED_${_component}) + foreach(_dependency ${}) + set(MagnumExtras_FIND_REQUIRED_${_dependency} TRUE) + endforeach() + endif() + + list(APPEND _MAGNUMEXTRAS_ADDITIONAL_COMPONENTS ${_MAGNUMEXTRAS_${_COMPONENT}_DEPENDENCIES}) +endforeach() + +# Join the lists, remove duplicate components +if(_MAGNUMEXTRAS_ADDITIONAL_COMPONENTS) + list(INSERT MagnumExtras_FIND_COMPONENTS 0 ${_MAGNUMEXTRAS_ADDITIONAL_COMPONENTS}) +endif() +if(MagnumExtras_FIND_COMPONENTS) + list(REMOVE_DUPLICATES MagnumExtras_FIND_COMPONENTS) +endif() + +# Component distinction (listing them explicitly to avoid mistakes with finding +# components from other repositories) +set(_MAGNUMEXTRAS_LIBRARY_COMPONENTS "(Octree|SceneGraph)") + +# Additional components +foreach(_component ${MagnumExtras_FIND_COMPONENTS}) + string(TOUPPER ${_component} _COMPONENT) + + # Create imported target in case the library is found. If the project is + # added as subproject to CMake, the target already exists and all the + # required setup is already done from the build tree. + if(TARGET MagnumExtras::${_component}) + set(MagnumExtras_${_component}_FOUND TRUE) + else() + # Library components + if(_component MATCHES ${_MAGNUMEXTRAS_LIBRARY_COMPONENTS}) + add_library(MagnumExtras::${_component} UNKNOWN IMPORTED) + + # Try to find both debug and release version + find_library(MAGNUMEXTRAS_${_COMPONENT}_LIBRARY_DEBUG Magnum${_component}-d) + find_library(MAGNUMEXTRAS_${_COMPONENT}_LIBRARY_RELEASE Magnum${_component}) + mark_as_advanced(MAGNUMEXTRAS_${_COMPONENT}_LIBRARY_DEBUG + MAGNUMEXTRAS_${_COMPONENT}_LIBRARY_RELEASE) + + if(MAGNUMEXTRAS_${_COMPONENT}_LIBRARY_RELEASE) + set_property(TARGET MagnumExtras::${_component} APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE) + set_property(TARGET MagnumExtras::${_component} PROPERTY + IMPORTED_LOCATION_RELEASE ${MAGNUMEXTRAS_${_COMPONENT}_LIBRARY_RELEASE}) + endif() + + if(MAGNUMEXTRAS_${_COMPONENT}_LIBRARY_DEBUG) + set_property(TARGET MagnumExtras::${_component} APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_property(TARGET MagnumExtras::${_component} PROPERTY + IMPORTED_LOCATION_DEBUG ${MAGNUMEXTRAS_${_COMPONENT}_LIBRARY_DEBUG}) + endif() + endif() + + # (none yet) + + # Find library includes + if(_component MATCHES ${_MAGNUMEXTRAS_LIBRARY_COMPONENTS}) + find_path(_MAGNUMEXTRAS_${_COMPONENT}_INCLUDE_DIR + NAMES ${_component}.h + HINTS ${MAGNUMEXTRAS_INCLUDE_DIR}/Magnum/${_component}) + endif() + + if(_component MATCHES ${_MAGNUMEXTRAS_LIBRARY_COMPONENTS}) + # Link to Corrade dependencies, link to core Magnum library and + # other Magnum dependencies + foreach(_dependency ${_MAGNUMEXTRAS_${_COMPONENT}_CORRADE_DEPENDENCIES}) + set_property(TARGET MagnumExtras::${_component} APPEND PROPERTY + INTERFACE_LINK_LIBRARIES Corrade::${_dependency}) + endforeach() + set_property(TARGET MagnumExtras::${_component} APPEND PROPERTY + INTERFACE_LINK_LIBRARIES Magnum::Magnum) + foreach(_dependency ${_MAGNUMEXTRAS_${_COMPONENT}_MAGNUM_DEPENDENCIES}) + set_property(TARGET MagnumExtras::${_component} APPEND PROPERTY + INTERFACE_LINK_LIBRARIES Magnum::${_dependency}) + endforeach() + + # Add inter-project dependencies + foreach(_dependency ${_MAGNUMEXTRAS_${_COMPONENT}_DEPENDENCIES}) + set_property(TARGET MagnumExtras::${_component} APPEND PROPERTY + INTERFACE_LINK_LIBRARIES MagnumExtras::${_dependency}) + endforeach() + endif() + + # Decide if the library was found + if(_component MATCHES ${_MAGNUMEXTRAS_LIBRARY_COMPONENTS} AND _MAGNUMEXTRAS_${_COMPONENT}_INCLUDE_DIR AND (MAGNUMEXTRAS_${_COMPONENT}_LIBRARY_DEBUG OR MAGNUMEXTRAS_${_COMPONENT}_LIBRARY_RELEASE)) + set(MagnumExtras_${_component}_FOUND TRUE) + else() + set(MagnumExtras_${_component}_FOUND FALSE) + endif() + endif() +endforeach() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(MagnumExtras + REQUIRED_VARS MAGNUMEXTRAS_INCLUDE_DIR + HANDLE_COMPONENTS) diff --git a/src/octree/OctreeExample.cpp b/src/octree/OctreeExample.cpp index 83320821c..ae82e0845 100644 --- a/src/octree/OctreeExample.cpp +++ b/src/octree/OctreeExample.cpp @@ -44,26 +44,22 @@ #include #include - namespace Magnum { namespace Examples { -using namespace SceneGraph; -using namespace DebugTools; - -typedef Scene Scene3D; -typedef Object Object3D; +typedef SceneGraph::Scene Scene3D; +typedef SceneGraph::Object Object3D; class FrustumDrawable: public Object3D, public SceneGraph::Drawable3D { public: explicit FrustumDrawable(Object3D* parent, SceneGraph::DrawableGroup3D* group, Mesh& mesh): Object3D{parent}, SceneGraph::Drawable3D{*this, group}, _mesh(mesh) { } private: - void draw(const Matrix4& transformationMatrix, Camera3D& camera) override { - /* The scaling in the TransformationProjectionMatrix for reflection, because of use of DirectX matrices instead of OpenGL ones */ + void draw(const Matrix4& transformationMatrix, SceneGraph::Camera3D& camera) override { _shader.setColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f)) - .setTransformationProjectionMatrix(camera.projectionMatrix() * transformationMatrix * Matrix4::scaling(Vector3{1, 1, -1})); + .setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix); _mesh.draw(_shader); } + Mesh& _mesh; Shaders::Flat3D _shader; }; @@ -74,6 +70,8 @@ class OctreeExample: public Platform::Application { private: void drawEvent() override; + void keyPressEvent(KeyEvent& event) override; + void addBox(Shapes::AxisAlignedBox3D& box); Vector3 calculateIntersection(const Vector4& v1, const Vector4& v2, const Vector4& v3); @@ -82,50 +80,53 @@ class OctreeExample: public Platform::Application { Scene3D _scene; Object3D _cameraObject; Object3D _viewerObject; - Camera3D _camera; /* camera which will be culled for */ - Camera3D _viewer; /* camera from which we will render */ + SceneGraph::Camera3D _camera; /* camera which will be culled for */ + SceneGraph::Camera3D _viewer; /* external camera */ + SceneGraph::Camera3D* _activeCamera; /* camera from which we will render */ - OctreeDrawableGroup _culledDrawables; - ShapeGroup<3> _shapes; + SceneGraph::OctreeDrawableGroup _culledDrawables; + SceneGraph::ShapeGroup<3> _shapes; - DrawableGroup3D _drawables; + SceneGraph::DrawableGroup3D _drawables; Buffer _buffer; Mesh _mesh; - }; OctreeExample::OctreeExample(const Arguments& arguments): - Platform::Application{arguments, Configuration{}.setTitle("Magnum Octree View Frustrum Culling Example")}, + Platform::Application{arguments, Configuration{}.setTitle("Magnum Octree View Frustrum Culling Example").setSampleCount(8)}, _cameraObject(&_scene), _viewerObject(&_scene), _camera(_cameraObject), - _viewer(_viewerObject) + _viewer(_viewerObject), + _activeCamera(&_viewer) { Renderer::enable(Renderer::Feature::DepthTest); - _camera.setProjectionMatrix(Matrix4::perspectiveProjection(75.0_degf, Vector2{defaultFramebuffer.viewport().size()}.aspectRatio(), 0.01f, 75.0f)); + _camera.setProjectionMatrix(Matrix4::perspectiveProjection(75.0_degf, Vector2{defaultFramebuffer.viewport().size()}.aspectRatio(), 0.5f, 75.0f)); _viewer.setProjectionMatrix(Matrix4::perspectiveProjection(75.0_degf, Vector2{defaultFramebuffer.viewport().size()}.aspectRatio(), 0.01f, 150.0f)); _manager.set("pink", DebugTools::ShapeRendererOptions().setColor({1.0f, 0.0f, 1.0f})); - //Setup _camera and _viewer transformation + /* Setup _camera and _viewer transformation */ _viewerObject.translate({0.0f, 10.0f, 50.0f}); _viewerObject.rotateXLocal(Deg(-10.0f)); - //create visualisation of _camera view frustum - const Matrix4 projection = Matrix4(_camera.projectionMatrix()).transposed(); - const Vector4 left{projection[3] + projection[0]}; - const Vector4 right{projection[3] - projection[0]}; - const Vector4 bottom{projection[3] + projection[1]}; - const Vector4 top{projection[3] - projection[1]}; - const Vector4 near{projection[2]}; - const Vector4 far{projection[3] - projection[2]}; + /* Create visualisation of _camera view frustum */ + const Matrix4 mvp = Matrix4(_camera.projectionMatrix()); + + const Vector4 left{mvp.row(3) + mvp.row(0)}; + const Vector4 right{mvp.row(3) - mvp.row(0)}; + const Vector4 bottom{mvp.row(3) + mvp.row(1)}; + const Vector4 top{mvp.row(3) - mvp.row(1)}; + const Vector4 near{mvp.row(3) + mvp.row(2)}; + const Vector4 far{mvp.row(3) - mvp.row(2)}; const Vector3 rbn = calculateIntersection(right, bottom, near); const Vector3 lbn = calculateIntersection(left, bottom, near); const Vector3 rtn = calculateIntersection(right, top, near); const Vector3 ltn = calculateIntersection(left, top, near); + const Vector3 rbf = calculateIntersection(right, bottom, far); const Vector3 lbf = calculateIntersection(left, bottom, far); const Vector3 rtf = calculateIntersection(right, top, far); @@ -154,46 +155,43 @@ OctreeExample::OctreeExample(const Arguments& arguments): //auto rightBox = Shapes::AxisAlignedBox3D(Vector3{10.0, -0.5, -15.5}, Vector3{11.0, 0.5, 0.5}); addBox(rightBox); - auto leftBox = Shapes::AxisAlignedBox3D(Vector3{-11.0, -0.5, -0.5}, Vector3{-10.0, 0.5, 0.5}); - addBox(leftBox); - - auto nearBox = Shapes::AxisAlignedBox3D(Vector3{-0.5, -0.5, 10.0}, Vector3{0.5, 0.5, 11.0}); - addBox(nearBox); + const float RAND_MAX_RANGE = float(RAND_MAX/40); + for(int i = 0; i < 1000; ++i) { + const Vector3 min = Vector3{float(std::rand())/RAND_MAX_RANGE, float(std::rand())/RAND_MAX_RANGE, float(std::rand())/RAND_MAX_RANGE} - Vector3{20.0f}; + auto box = Shapes::AxisAlignedBox3D(min, min + Vector3{1.0f}); + addBox(box); + } - auto farBox = Shapes::AxisAlignedBox3D(Vector3{-0.5, -0.5, -11.0}, Vector3{0.5, 0.5, -10.0}); - addBox(farBox); - - auto originBox = Shapes::AxisAlignedBox3D(Vector3{-0.5}, Vector3{0.5}); + auto originBox = Shapes::AxisAlignedBox3D(Vector3{-1.0f}, Vector3{1.0f}); addBox(originBox); - //breaks the culling - //auto shape5 = Shapes::AxisAlignedBox3D(Vector3{-25.5, 5.5, -46.5}, Vector3{-24.5, 6.5, -45.5}); - //addBox(shape5); + // breaks the culling + // auto shape5 = Shapes::AxisAlignedBox3D(Vector3{-25.5, 5.5, -46.5}, Vector3{-24.5, 6.5, -45.5}); + // addBox(shape5); } Vector3 OctreeExample::calculateIntersection(const Vector4 &v1, const Vector4 &v2, const Vector4 &v3) { - - const Float det = Matrix3(v1.xyz(), v2.xyz(), v3.xyz()).transposed().determinant(); + const Float det = Matrix3(v1.xyz(), v2.xyz(), v3.xyz()).determinant(); const Float x = Matrix3({v1.w(), v2.w(), v3.w()}, {v1.y(), v2.y(), v3.y()}, {v1.z(), v2.z(), v3.z()}).determinant() / det; const Float y = Matrix3({v1.x(), v2.x(), v3.x()}, {v1.w(), v2.w(), v3.w()}, {v1.z(), v2.z(), v3.z()}).determinant() / det; const Float z = Matrix3({v1.x(), v2.x(), v3.x()}, {v1.y(), v2.y(), v3.y()}, {v1.w(), v2.w(), v3.w()}).determinant() / det; - return Vector3{x, y, z}; + return Vector3{x, y, -z}; } void OctreeExample::addBox(Shapes::AxisAlignedBox3D& aabox) { - const Vector3 s = aabox.max() - aabox.min(); - const Vector3 t = aabox.min() + s/2; - const Matrix4 transformationMatrix = Matrix4::translation(t) * Matrix4::scaling(s); + const Vector3 size = aabox.max() - aabox.min(); + const Vector3 center = aabox.min() + size/2; + const Matrix4 transformationMatrix = Matrix4::translation(center) * Matrix4::scaling(size); Shapes::Shape* box = new Shapes::Shape(_scene, transformationMatrix, &_shapes); new DebugTools::ShapeRenderer3D(*box, ResourceKey("pink"), &_culledDrawables); // TODO: maybe randomize the color? *later* - ShapeRenderer<3>* renderer = new ShapeRenderer<3>(*box, ResourceKey("pink")); + DebugTools::ShapeRenderer<3>* renderer = new DebugTools::ShapeRenderer<3>(*box, ResourceKey("pink")); _culledDrawables.add(*renderer, aabox); } @@ -201,20 +199,32 @@ void OctreeExample::addBox(Shapes::AxisAlignedBox3D& aabox) { void OctreeExample::drawEvent() { defaultFramebuffer.clear(FramebufferClear::Color | FramebufferClear::Depth); - // cull for _camera + /* cull for _camera */ _culledDrawables.buildOctree(); _culledDrawables.cull(_camera); - _viewer.draw(_culledDrawables); - _viewer.draw(_drawables); + _activeCamera->draw(_culledDrawables); + _activeCamera->draw(_drawables); + swapBuffers(); - // rotate _camera to change cull result + /* Rotate _camera to change cull result */ _cameraObject.rotateYLocal(Deg(0.5f)); redraw(); } +void OctreeExample::keyPressEvent(KeyEvent& event) { + if(event.key() == KeyEvent::Key::S) { + /* Switch view */ + if(_activeCamera == &_viewer) { + _activeCamera = &_camera; + } else { + _activeCamera = &_viewer; + } + } +} + }} MAGNUM_APPLICATION_MAIN(Magnum::Examples::OctreeExample) From d3889313fff9ddb0610cff991a6fc86751bc793a Mon Sep 17 00:00:00 2001 From: Squareys Date: Fri, 16 Sep 2016 10:35:30 +0200 Subject: [PATCH 04/10] octree: Update cmake project Signed-off-by: Squareys --- src/octree/CMakeLists.txt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/octree/CMakeLists.txt b/src/octree/CMakeLists.txt index 8aed5d704..5a64e2e51 100644 --- a/src/octree/CMakeLists.txt +++ b/src/octree/CMakeLists.txt @@ -24,7 +24,7 @@ # DEALINGS IN THE SOFTWARE. # -cmake_minimum_required(VERSION 2.8.9) +cmake_minimum_required(VERSION 2.8.12) project(MagnumOctreeExample) # CMake policies: enable MACOSX_RPATH by default @@ -37,24 +37,26 @@ if(POLICY CMP0028) endif() find_package(Magnum REQUIRED - DebugTools SceneGraph + Primitives Sdl2Application) find_package(MagnumExtras REQUIRED Octree SceneGraph) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CORRADE_CXX_FLAGS}") -include_directories(${MAGNUM_INCLUDE_DIRS} ${MAGNUM_OCTREE_INCLUDE_DIRS} ${MAGNUM_APPLICATION_INCLUDE_DIRS}) add_executable(magnum-octree OctreeExample.cpp) target_link_libraries(magnum-octree - ${MAGNUM_LIBRARIES} - ${MAGNUM_DEBUGTOOLS_LIBRARIES} - ${MAGNUMEXTRAS_SCENEGRAPH_LIBRARIES} - ${MAGNUMEXTRAS_OCTREE_LIBRARIES} - ${MAGNUM_APPLICATION_LIBRARIES}) + Magnum::Magnum + Magnum::SceneGraph + Magnum::Primitives + Magnum::Application + MagnumExtras::Octree) + +target_compile_features(magnum-octree PRIVATE cxx_range_for) install(TARGETS magnum-octree DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}) install(FILES README.md DESTINATION ${MAGNUM_DATA_INSTALL_DIR}/examples RENAME README-octree.md) From 0dba717a38a4a7d0f5fb0c2286cc25524d3fcb3e Mon Sep 17 00:00:00 2001 From: Squareys Date: Fri, 16 Sep 2016 10:35:44 +0200 Subject: [PATCH 05/10] octree: Use meshes instead of ShapeRenderer Signed-off-by: Squareys --- src/octree/OctreeExample.cpp | 47 +++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/octree/OctreeExample.cpp b/src/octree/OctreeExample.cpp index ae82e0845..ce5dd523e 100644 --- a/src/octree/OctreeExample.cpp +++ b/src/octree/OctreeExample.cpp @@ -26,8 +26,6 @@ */ #include -#include -#include #include #include #include @@ -35,33 +33,41 @@ #include #include #include -#include -#include -#include -#include +#include #include #include #include #include +#include namespace Magnum { namespace Examples { typedef SceneGraph::Scene Scene3D; typedef SceneGraph::Object Object3D; -class FrustumDrawable: public Object3D, public SceneGraph::Drawable3D { +const Color3 PINK{1.0f, 0.0f, 1.0f}; +const Color3 WHITE{1.0f, 1.0f, 1.0f}; + +class WireframeDrawable: public Object3D, public SceneGraph::Drawable3D { public: - explicit FrustumDrawable(Object3D* parent, SceneGraph::DrawableGroup3D* group, Mesh& mesh): Object3D{parent}, SceneGraph::Drawable3D{*this, group}, _mesh(mesh) { + explicit WireframeDrawable(Object3D* parent, SceneGraph::DrawableGroup3D* group, Mesh& mesh): Object3D{parent}, SceneGraph::Drawable3D{*this, group}, _mesh(mesh) { + } + + WireframeDrawable& setColor(const Color3& color) { + _color = color; + return *this; } + private: void draw(const Matrix4& transformationMatrix, SceneGraph::Camera3D& camera) override { - _shader.setColor(Color3::fromHSV(216.0_degf, 0.85f, 1.0f)) + _shader.setColor(_color) .setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix); _mesh.draw(_shader); } Mesh& _mesh; Shaders::Flat3D _shader; + Color3 _color; }; class OctreeExample: public Platform::Application { @@ -75,8 +81,6 @@ class OctreeExample: public Platform::Application { void addBox(Shapes::AxisAlignedBox3D& box); Vector3 calculateIntersection(const Vector4& v1, const Vector4& v2, const Vector4& v3); - DebugTools::ResourceManager _manager; - Scene3D _scene; Object3D _cameraObject; Object3D _viewerObject; @@ -85,12 +89,13 @@ class OctreeExample: public Platform::Application { SceneGraph::Camera3D* _activeCamera; /* camera from which we will render */ SceneGraph::OctreeDrawableGroup _culledDrawables; - SceneGraph::ShapeGroup<3> _shapes; - SceneGraph::DrawableGroup3D _drawables; Buffer _buffer; Mesh _mesh; + + Buffer _cubeBuffer; + Mesh _cubeMesh; }; OctreeExample::OctreeExample(const Arguments& arguments): @@ -106,8 +111,6 @@ OctreeExample::OctreeExample(const Arguments& arguments): _camera.setProjectionMatrix(Matrix4::perspectiveProjection(75.0_degf, Vector2{defaultFramebuffer.viewport().size()}.aspectRatio(), 0.5f, 75.0f)); _viewer.setProjectionMatrix(Matrix4::perspectiveProjection(75.0_degf, Vector2{defaultFramebuffer.viewport().size()}.aspectRatio(), 0.01f, 150.0f)); - _manager.set("pink", DebugTools::ShapeRendererOptions().setColor({1.0f, 0.0f, 1.0f})); - /* Setup _camera and _viewer transformation */ _viewerObject.translate({0.0f, 10.0f, 50.0f}); _viewerObject.rotateXLocal(Deg(-10.0f)); @@ -144,7 +147,13 @@ OctreeExample::OctreeExample(const Arguments& arguments): .setCount(16) .addVertexBuffer(_buffer, 0, Shaders::Flat3D::Position{}); - new FrustumDrawable(&_cameraObject, &_drawables, _mesh); + (new WireframeDrawable(&_cameraObject, &_drawables, _mesh))->setColor(WHITE); + + Trade::MeshData3D cubeData = Primitives::Cube::wireframe(); + _cubeBuffer.setData(cubeData.positions(0), BufferUsage::StaticDraw); + _cubeMesh.setPrimitive(cubeData.primitive()) + .addVertexBuffer(_cubeBuffer, 0, Shaders::Flat3D::Position{}) + .setCount(cubeData.positions(0).size()); // TODO: add more boxes // TODO: Do it with a loop and random values @@ -187,11 +196,9 @@ void OctreeExample::addBox(Shapes::AxisAlignedBox3D& aabox) { const Vector3 center = aabox.min() + size/2; const Matrix4 transformationMatrix = Matrix4::translation(center) * Matrix4::scaling(size); - Shapes::Shape* box = new Shapes::Shape(_scene, transformationMatrix, &_shapes); - new DebugTools::ShapeRenderer3D(*box, ResourceKey("pink"), &_culledDrawables); - + Object3D* box = new Object3D{&_scene}; // TODO: maybe randomize the color? *later* - DebugTools::ShapeRenderer<3>* renderer = new DebugTools::ShapeRenderer<3>(*box, ResourceKey("pink")); + WireframeDrawable* renderer = new WireframeDrawable(box, &_drawables, _cubeMesh); _culledDrawables.add(*renderer, aabox); } From 180161e21708c0ff53b75a08e1a004dfa34b9f41 Mon Sep 17 00:00:00 2001 From: Squareys Date: Fri, 16 Sep 2016 22:17:27 +0200 Subject: [PATCH 06/10] octree: Cleanup and replace AABB with Range3D. Signed-off-by: Squareys --- src/octree/CMakeLists.txt | 7 +++-- src/octree/OctreeExample.cpp | 61 +++++++++++++++++------------------- 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/octree/CMakeLists.txt b/src/octree/CMakeLists.txt index 5a64e2e51..9202856d4 100644 --- a/src/octree/CMakeLists.txt +++ b/src/octree/CMakeLists.txt @@ -38,6 +38,7 @@ endif() find_package(Magnum REQUIRED SceneGraph + Shaders Primitives Sdl2Application) @@ -50,11 +51,13 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CORRADE_CXX_FLAGS}") add_executable(magnum-octree OctreeExample.cpp) target_link_libraries(magnum-octree - Magnum::Magnum + Magnum::Shaders Magnum::SceneGraph Magnum::Primitives Magnum::Application - MagnumExtras::Octree) + MagnumExtras::Octree + MagnumExtras::SceneGraph + Magnum::Magnum) target_compile_features(magnum-octree PRIVATE cxx_range_for) diff --git a/src/octree/OctreeExample.cpp b/src/octree/OctreeExample.cpp index ce5dd523e..775b3fb0e 100644 --- a/src/octree/OctreeExample.cpp +++ b/src/octree/OctreeExample.cpp @@ -47,10 +47,13 @@ typedef SceneGraph::Object Object3D; const Color3 PINK{1.0f, 0.0f, 1.0f}; const Color3 WHITE{1.0f, 1.0f, 1.0f}; +const Color3 LIGHT_GREY{0.5f, 0.5f, 0.5f}; class WireframeDrawable: public Object3D, public SceneGraph::Drawable3D { public: - explicit WireframeDrawable(Object3D* parent, SceneGraph::DrawableGroup3D* group, Mesh& mesh): Object3D{parent}, SceneGraph::Drawable3D{*this, group}, _mesh(mesh) { + explicit WireframeDrawable(Object3D* parent, SceneGraph::DrawableGroup3D* group, Mesh& mesh, Shaders::Flat3D& shader): + Object3D{parent}, SceneGraph::Drawable3D{*this, group}, _mesh(mesh), _shader{shader} + { } WireframeDrawable& setColor(const Color3& color) { @@ -66,7 +69,7 @@ class WireframeDrawable: public Object3D, public SceneGraph::Drawable3D { } Mesh& _mesh; - Shaders::Flat3D _shader; + Shaders::Flat3D& _shader; Color3 _color; }; @@ -78,7 +81,7 @@ class OctreeExample: public Platform::Application { void drawEvent() override; void keyPressEvent(KeyEvent& event) override; - void addBox(Shapes::AxisAlignedBox3D& box); + void addBox(const Range3D& box); Vector3 calculateIntersection(const Vector4& v1, const Vector4& v2, const Vector4& v3); Scene3D _scene; @@ -95,7 +98,10 @@ class OctreeExample: public Platform::Application { Mesh _mesh; Buffer _cubeBuffer; + Buffer _cubeIndexBuffer; Mesh _cubeMesh; + + Shaders::Flat3D _flatShader; }; OctreeExample::OctreeExample(const Arguments& arguments): @@ -147,36 +153,25 @@ OctreeExample::OctreeExample(const Arguments& arguments): .setCount(16) .addVertexBuffer(_buffer, 0, Shaders::Flat3D::Position{}); - (new WireframeDrawable(&_cameraObject, &_drawables, _mesh))->setColor(WHITE); + (new WireframeDrawable(&_cameraObject, &_drawables, _mesh, _flatShader))->setColor(WHITE); Trade::MeshData3D cubeData = Primitives::Cube::wireframe(); _cubeBuffer.setData(cubeData.positions(0), BufferUsage::StaticDraw); + _cubeIndexBuffer.setData(cubeData.indices(), BufferUsage::StaticDraw); _cubeMesh.setPrimitive(cubeData.primitive()) .addVertexBuffer(_cubeBuffer, 0, Shaders::Flat3D::Position{}) - .setCount(cubeData.positions(0).size()); - - // TODO: add more boxes - // TODO: Do it with a loop and random values - auto rightBox = Shapes::AxisAlignedBox3D(Vector3{10.0, -0.5, -0.5}, Vector3{11.0, 0.5, 0.5}); - //doesn't break the culling - //auto rightBox = Shapes::AxisAlignedBox3D(Vector3{10.0, -0.5, -10.5}, Vector3{11.0, 0.5, 0.5}); - //breaks the culling - //auto rightBox = Shapes::AxisAlignedBox3D(Vector3{10.0, -0.5, -15.5}, Vector3{11.0, 0.5, 0.5}); - addBox(rightBox); - - const float RAND_MAX_RANGE = float(RAND_MAX/40); - for(int i = 0; i < 1000; ++i) { - const Vector3 min = Vector3{float(std::rand())/RAND_MAX_RANGE, float(std::rand())/RAND_MAX_RANGE, float(std::rand())/RAND_MAX_RANGE} - Vector3{20.0f}; - auto box = Shapes::AxisAlignedBox3D(min, min + Vector3{1.0f}); + .setIndexBuffer(_cubeIndexBuffer, 0, Mesh::IndexType::UnsignedInt) + .setCount(cubeData.indices().size()); + + const float RAND_MAX_RANGE = float(RAND_MAX/60); + for(int i = 0; i < 10000; ++i) { + const Vector3 randomVector{float(std::rand()), float(std::rand()), float(std::rand())}; + const Vector3 min = randomVector/RAND_MAX_RANGE - Vector3{30.0f}; + auto box = Range3D(min, min + Vector3{1.0f}); addBox(box); } - auto originBox = Shapes::AxisAlignedBox3D(Vector3{-1.0f}, Vector3{1.0f}); - addBox(originBox); - - // breaks the culling - // auto shape5 = Shapes::AxisAlignedBox3D(Vector3{-25.5, 5.5, -46.5}, Vector3{-24.5, 6.5, -45.5}); - // addBox(shape5); + _culledDrawables.buildOctree(4); } @@ -190,15 +185,16 @@ Vector3 OctreeExample::calculateIntersection(const Vector4 &v1, const Vector4 &v return Vector3{x, y, -z}; } -void OctreeExample::addBox(Shapes::AxisAlignedBox3D& aabox) { - - const Vector3 size = aabox.max() - aabox.min(); - const Vector3 center = aabox.min() + size/2; - const Matrix4 transformationMatrix = Matrix4::translation(center) * Matrix4::scaling(size); +void OctreeExample::addBox(const Range3D& aabox) { + const Matrix4 transformationMatrix = Matrix4::translation(aabox.center()) * Matrix4::scaling(aabox.size()/2); Object3D* box = new Object3D{&_scene}; - // TODO: maybe randomize the color? *later* - WireframeDrawable* renderer = new WireframeDrawable(box, &_drawables, _cubeMesh); + box->setTransformation(transformationMatrix); + + (new WireframeDrawable(box, &_drawables, _cubeMesh, _flatShader))->setColor(LIGHT_GREY); + + WireframeDrawable* renderer = new WireframeDrawable(box, nullptr, _cubeMesh, _flatShader); + renderer->setColor(PINK); _culledDrawables.add(*renderer, aabox); } @@ -207,7 +203,6 @@ void OctreeExample::drawEvent() { defaultFramebuffer.clear(FramebufferClear::Color | FramebufferClear::Depth); /* cull for _camera */ - _culledDrawables.buildOctree(); _culledDrawables.cull(_camera); _activeCamera->draw(_culledDrawables); From 74d89b66b48471dd7baea1c2ab45d647a15ef055 Mon Sep 17 00:00:00 2001 From: Squareys Date: Fri, 16 Sep 2016 22:18:30 +0200 Subject: [PATCH 07/10] octree: Add toggleable visualization for octree. Signed-off-by: Squareys --- src/octree/OctreeExample.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/octree/OctreeExample.cpp b/src/octree/OctreeExample.cpp index 775b3fb0e..4dc81e93c 100644 --- a/src/octree/OctreeExample.cpp +++ b/src/octree/OctreeExample.cpp @@ -48,6 +48,7 @@ typedef SceneGraph::Object Object3D; const Color3 PINK{1.0f, 0.0f, 1.0f}; const Color3 WHITE{1.0f, 1.0f, 1.0f}; const Color3 LIGHT_GREY{0.5f, 0.5f, 0.5f}; +const Color3 GREEN{0.0f, 0.2f, 0.0f}; class WireframeDrawable: public Object3D, public SceneGraph::Drawable3D { public: @@ -84,15 +85,19 @@ class OctreeExample: public Platform::Application { void addBox(const Range3D& box); Vector3 calculateIntersection(const Vector4& v1, const Vector4& v2, const Vector4& v3); + void addDrawableForOctree(Octree::Octree*>& octree); + Scene3D _scene; Object3D _cameraObject; Object3D _viewerObject; + Object3D _octreeObject; SceneGraph::Camera3D _camera; /* camera which will be culled for */ SceneGraph::Camera3D _viewer; /* external camera */ SceneGraph::Camera3D* _activeCamera; /* camera from which we will render */ SceneGraph::OctreeDrawableGroup _culledDrawables; SceneGraph::DrawableGroup3D _drawables; + SceneGraph::DrawableGroup3D _octreeVisualization; Buffer _buffer; Mesh _mesh; @@ -102,12 +107,15 @@ class OctreeExample: public Platform::Application { Mesh _cubeMesh; Shaders::Flat3D _flatShader; + + bool _visualizeOctree = true; }; OctreeExample::OctreeExample(const Arguments& arguments): Platform::Application{arguments, Configuration{}.setTitle("Magnum Octree View Frustrum Culling Example").setSampleCount(8)}, _cameraObject(&_scene), _viewerObject(&_scene), + _octreeObject{&_scene}, _camera(_cameraObject), _viewer(_viewerObject), _activeCamera(&_viewer) @@ -173,6 +181,7 @@ OctreeExample::OctreeExample(const Arguments& arguments): _culledDrawables.buildOctree(4); + addDrawableForOctree(*_culledDrawables.octree()); } Vector3 OctreeExample::calculateIntersection(const Vector4 &v1, const Vector4 &v2, const Vector4 &v3) { @@ -199,6 +208,21 @@ void OctreeExample::addBox(const Range3D& aabox) { _culledDrawables.add(*renderer, aabox); } +void OctreeExample::addDrawableForOctree(Octree::Octree*>& octree) { + if(octree.isLeafNode()) { + const Matrix4 transformationMatrix = Matrix4::translation(octree.center())*Matrix4::scaling(Vector3{octree.radius()*0.999f}); + + Object3D* box = new Object3D{&_octreeObject}; + box->setTransformation(transformationMatrix); + + (new WireframeDrawable(box, &_octreeVisualization, _cubeMesh, _flatShader))->setColor(GREEN * float(octree.depth())); + } else { + for(int i = 0; i < 8; ++i) { + addDrawableForOctree(*octree.child(i)); + } + } +} + void OctreeExample::drawEvent() { defaultFramebuffer.clear(FramebufferClear::Color | FramebufferClear::Depth); @@ -207,6 +231,9 @@ void OctreeExample::drawEvent() { _activeCamera->draw(_culledDrawables); _activeCamera->draw(_drawables); + if(_visualizeOctree) { + _activeCamera->draw(_octreeVisualization); + } swapBuffers(); @@ -224,6 +251,8 @@ void OctreeExample::keyPressEvent(KeyEvent& event) { } else { _activeCamera = &_viewer; } + } else if(event.key() == KeyEvent::Key::V) { + _visualizeOctree = !_visualizeOctree; } } From 2721b95a5225e8b4c0a9b79d871d39f677651bb2 Mon Sep 17 00:00:00 2001 From: Squareys Date: Fri, 16 Sep 2016 22:18:41 +0200 Subject: [PATCH 08/10] octree: Exit on Esc Signed-off-by: Squareys --- src/octree/OctreeExample.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/octree/OctreeExample.cpp b/src/octree/OctreeExample.cpp index 4dc81e93c..ad7ad0f30 100644 --- a/src/octree/OctreeExample.cpp +++ b/src/octree/OctreeExample.cpp @@ -253,6 +253,8 @@ void OctreeExample::keyPressEvent(KeyEvent& event) { } } else if(event.key() == KeyEvent::Key::V) { _visualizeOctree = !_visualizeOctree; + } else if(event.key() == KeyEvent::Key::Esc) { + exit(); } } From e218d2a4823bc2a2037233a6532c7f357331effd Mon Sep 17 00:00:00 2001 From: Squareys Date: Fri, 16 Sep 2016 22:19:36 +0200 Subject: [PATCH 09/10] octree: Only draw culled drawables when not in external view. Signed-off-by: Squareys --- src/octree/OctreeExample.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/octree/OctreeExample.cpp b/src/octree/OctreeExample.cpp index ad7ad0f30..30efb6a9c 100644 --- a/src/octree/OctreeExample.cpp +++ b/src/octree/OctreeExample.cpp @@ -230,7 +230,10 @@ void OctreeExample::drawEvent() { _culledDrawables.cull(_camera); _activeCamera->draw(_culledDrawables); - _activeCamera->draw(_drawables); + + if(_activeCamera == &_viewer) { + _activeCamera->draw(_drawables); + } if(_visualizeOctree) { _activeCamera->draw(_octreeVisualization); } From b991446fdd1440dbf21158067e35a55f30aabdcc Mon Sep 17 00:00:00 2001 From: Squareys Date: Mon, 16 Apr 2018 08:26:21 +0200 Subject: [PATCH 10/10] octree: Adapt to magnum changes --- src/octree/OctreeExample.cpp | 45 +++++++++++++++--------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/src/octree/OctreeExample.cpp b/src/octree/OctreeExample.cpp index 30efb6a9c..ce8f6645d 100644 --- a/src/octree/OctreeExample.cpp +++ b/src/octree/OctreeExample.cpp @@ -30,8 +30,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -91,9 +91,9 @@ class OctreeExample: public Platform::Application { Object3D _cameraObject; Object3D _viewerObject; Object3D _octreeObject; - SceneGraph::Camera3D _camera; /* camera which will be culled for */ - SceneGraph::Camera3D _viewer; /* external camera */ - SceneGraph::Camera3D* _activeCamera; /* camera from which we will render */ + SceneGraph::Camera3D _camera; /* Camera which will be culled for */ + SceneGraph::Camera3D _viewer; /* External camera */ + SceneGraph::Camera3D* _activeCamera; /* Camera from which we will render */ SceneGraph::OctreeDrawableGroup _culledDrawables; SceneGraph::DrawableGroup3D _drawables; @@ -132,6 +132,7 @@ OctreeExample::OctreeExample(const Arguments& arguments): /* Create visualisation of _camera view frustum */ const Matrix4 mvp = Matrix4(_camera.projectionMatrix()); + // TODO: Use Frustum::fromMatrix() const Vector4 left{mvp.row(3) + mvp.row(0)}; const Vector4 right{mvp.row(3) - mvp.row(0)}; const Vector4 bottom{mvp.row(3) + mvp.row(1)}; @@ -187,9 +188,9 @@ OctreeExample::OctreeExample(const Arguments& arguments): Vector3 OctreeExample::calculateIntersection(const Vector4 &v1, const Vector4 &v2, const Vector4 &v3) { const Float det = Matrix3(v1.xyz(), v2.xyz(), v3.xyz()).determinant(); - const Float x = Matrix3({v1.w(), v2.w(), v3.w()}, {v1.y(), v2.y(), v3.y()}, {v1.z(), v2.z(), v3.z()}).determinant() / det; - const Float y = Matrix3({v1.x(), v2.x(), v3.x()}, {v1.w(), v2.w(), v3.w()}, {v1.z(), v2.z(), v3.z()}).determinant() / det; - const Float z = Matrix3({v1.x(), v2.x(), v3.x()}, {v1.y(), v2.y(), v3.y()}, {v1.w(), v2.w(), v3.w()}).determinant() / det; + const Float x = Matrix3({v1.w(), v2.w(), v3.w()}, {v1.y(), v2.y(), v3.y()}, {v1.z(), v2.z(), v3.z()}).determinant()/det; + const Float y = Matrix3({v1.x(), v2.x(), v3.x()}, {v1.w(), v2.w(), v3.w()}, {v1.z(), v2.z(), v3.z()}).determinant()/det; + const Float z = Matrix3({v1.x(), v2.x(), v3.x()}, {v1.y(), v2.y(), v3.y()}, {v1.w(), v2.w(), v3.w()}).determinant()/det; return Vector3{x, y, -z}; } @@ -209,16 +210,16 @@ void OctreeExample::addBox(const Range3D& aabox) { } void OctreeExample::addDrawableForOctree(Octree::Octree*>& octree) { - if(octree.isLeafNode()) { - const Matrix4 transformationMatrix = Matrix4::translation(octree.center())*Matrix4::scaling(Vector3{octree.radius()*0.999f}); + if(octree.isLeafNode(0)) { + //const Matrix4 transformationMatrix = Matrix4::translation(octree.center())*Matrix4::scaling(Vector3{octree.radius()*0.999f}); - Object3D* box = new Object3D{&_octreeObject}; - box->setTransformation(transformationMatrix); + //Object3D* box = new Object3D{&_octreeObject}; + //box->setTransformation(transformationMatrix); - (new WireframeDrawable(box, &_octreeVisualization, _cubeMesh, _flatShader))->setColor(GREEN * float(octree.depth())); + //(new WireframeDrawable(box, &_octreeVisualization, _cubeMesh, _flatShader))->setColor(GREEN * float(octree.depth())); } else { for(int i = 0; i < 8; ++i) { - addDrawableForOctree(*octree.child(i)); + //addDrawableForOctree(*octree.child(i)); } } } @@ -231,12 +232,8 @@ void OctreeExample::drawEvent() { _activeCamera->draw(_culledDrawables); - if(_activeCamera == &_viewer) { - _activeCamera->draw(_drawables); - } - if(_visualizeOctree) { - _activeCamera->draw(_octreeVisualization); - } + if(_activeCamera == &_viewer) _activeCamera->draw(_drawables); + if(_visualizeOctree) _activeCamera->draw(_octreeVisualization); swapBuffers(); @@ -248,12 +245,8 @@ void OctreeExample::drawEvent() { void OctreeExample::keyPressEvent(KeyEvent& event) { if(event.key() == KeyEvent::Key::S) { - /* Switch view */ - if(_activeCamera == &_viewer) { - _activeCamera = &_camera; - } else { - _activeCamera = &_viewer; - } + /* Toggle view */ + _activeCamera = (_activeCamera == &_viewer) ? &_camera : &_viewer; } else if(event.key() == KeyEvent::Key::V) { _visualizeOctree = !_visualizeOctree; } else if(event.key() == KeyEvent::Key::Esc) {