From 7829b2454507b99f19acac04d216ca45df0b3acb Mon Sep 17 00:00:00 2001 From: Daniel Nachbaur Date: Fri, 10 Feb 2017 16:54:52 +0100 Subject: [PATCH] Move high-level classes for ClipPlanes and Histogram from Livre --- .gitsubprojects | 3 +- CMakeLists.txt | 7 +-- lexis/CMakeLists.txt | 16 ++++-- lexis/render/ClipPlanes.cpp | 54 +++++++++++++++++++ lexis/render/ClipPlanes.h | 39 ++++++++++++++ lexis/render/Histogram.cpp | 104 ++++++++++++++++++++++++++++++++++++ lexis/render/Histogram.h | 67 +++++++++++++++++++++++ lexis/render/clipPlanes.fbs | 2 +- lexis/render/histogram.fbs | 2 +- tests/render/clipPlanes.cpp | 41 ++++++++++++++ 10 files changed, 326 insertions(+), 9 deletions(-) create mode 100644 lexis/render/ClipPlanes.cpp create mode 100644 lexis/render/ClipPlanes.h create mode 100644 lexis/render/Histogram.cpp create mode 100644 lexis/render/Histogram.h create mode 100644 tests/render/clipPlanes.cpp diff --git a/.gitsubprojects b/.gitsubprojects index 96226c2..2dc74d4 100644 --- a/.gitsubprojects +++ b/.gitsubprojects @@ -1,3 +1,4 @@ # -*- mode: cmake -*- -git_subproject(ZeroBuf https://github.com/HBPVIS/ZeroBuf.git fdb57a3) +git_subproject(vmmlib https://github.com/Eyescale/vmmlib.git cfa6243) +git_subproject(ZeroBuf https://github.com/HBPVIS/ZeroBuf.git cea0338) git_subproject(ZeroEQ https://github.com/HBPVIS/ZeroEQ.git 847025a) diff --git a/CMakeLists.txt b/CMakeLists.txt index a1b9646..3c51520 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,9 @@ -# Copyright (c) HBP 2016 Daniel.Nachbaur@epfl.ch +# Copyright (c) HBP 2016-2017 Daniel.Nachbaur@epfl.ch # All rights reserved. Do not distribute without further notice. cmake_minimum_required(VERSION 3.1 FATAL_ERROR) -project(Lexis VERSION 1.1.0) -set(Lexis_VERSION_ABI 2) +project(Lexis VERSION 1.2.0) +set(Lexis_VERSION_ABI 3) list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake ${CMAKE_SOURCE_DIR}/CMake/common) @@ -18,6 +18,7 @@ set(COMMON_PROJECT_DOMAIN ch.epfl.bluebrain) include(Common) common_find_package(Boost COMPONENTS unit_test_framework) common_find_package(Qt5Core) +common_find_package(vmmlib REQUIRED) common_find_package(ZeroBuf REQUIRED) common_find_package(ZeroEQ) common_find_package_post() diff --git a/lexis/CMakeLists.txt b/lexis/CMakeLists.txt index 3d23bea..d493011 100644 --- a/lexis/CMakeLists.txt +++ b/lexis/CMakeLists.txt @@ -22,34 +22,44 @@ zerobuf_generate_cxx(LEXIS_DATA_DETAIL ${LEXIS_DATA_DIR}/detail set(LEXIS_RENDER_DIR ${__outdir}/render) set(LEXIS_RENDER_FBS ${CMAKE_CURRENT_SOURCE_DIR}/render/materialLUT.fbs - ${CMAKE_CURRENT_SOURCE_DIR}/render/clipPlanes.fbs ${CMAKE_CURRENT_SOURCE_DIR}/render/exit.fbs ${CMAKE_CURRENT_SOURCE_DIR}/render/frame.fbs - ${CMAKE_CURRENT_SOURCE_DIR}/render/histogram.fbs ${CMAKE_CURRENT_SOURCE_DIR}/render/imageJPEG.fbs ${CMAKE_CURRENT_SOURCE_DIR}/render/lookOut.fbs ${CMAKE_CURRENT_SOURCE_DIR}/render/lookupTable1D.fbs ${CMAKE_CURRENT_SOURCE_DIR}/render/stream.fbs ${CMAKE_CURRENT_SOURCE_DIR}/render/viewport.fbs ) +set(LEXIS_RENDER_DETAIL_FBS + ${CMAKE_CURRENT_SOURCE_DIR}/render/clipPlanes.fbs + ${CMAKE_CURRENT_SOURCE_DIR}/render/histogram.fbs +) zerobuf_generate_cxx(LEXIS_RENDER ${LEXIS_RENDER_DIR} ${LEXIS_RENDER_FBS}) +zerobuf_generate_cxx(LEXIS_RENDER_DETAIL ${LEXIS_RENDER_DIR}/detail + ${LEXIS_RENDER_DETAIL_FBS}) set(LEXIS_PUBLIC_HEADERS ${LEXIS_HEADERS} ${LEXIS_DATA_HEADERS} ${LEXIS_DATA_DETAIL_HEADERS} ${LEXIS_RENDER_HEADERS} + ${LEXIS_RENDER_DETAIL_HEADERS} data/Progress.h + render/ClipPlanes.h + render/Histogram.h ) list(APPEND LEXIS_SOURCES ${LEXIS_DATA_SOURCES} ${LEXIS_DATA_DETAIL_SOURCES} ${LEXIS_RENDER_SOURCES} + ${LEXIS_RENDER_DETAIL_SOURCES} data/Progress.cpp + render/ClipPlanes.cpp + render/Histogram.cpp ) -set(LEXIS_LINK_LIBRARIES PUBLIC ZeroBuf) +set(LEXIS_LINK_LIBRARIES PUBLIC vmmlib ZeroBuf) common_library(Lexis) diff --git a/lexis/render/ClipPlanes.cpp b/lexis/render/ClipPlanes.cpp new file mode 100644 index 0000000..8dd37fe --- /dev/null +++ b/lexis/render/ClipPlanes.cpp @@ -0,0 +1,54 @@ +/* Copyright (c) 2016-2017, Human Brain Project + * Ahmet.Bilgili@epfl.ch + */ + +#include "ClipPlanes.h" + +#include + +namespace lexis +{ +namespace render +{ + +ClipPlanes::ClipPlanes() +{ + reset(); +} + +bool ClipPlanes::isEmpty() const +{ + return getPlanes().empty(); +} + +void ClipPlanes::clear() +{ + getPlanes().clear(); +} + +void ClipPlanes::reset() +{ + setPlanes( { + { { -1.0f, 0.0f, 0.0f }, 0.5f }, // +X plane + { { 1.0f, 0.0f, 0.0f }, 0.5f }, // -X plane + { { 0.0f, -1.0f, 0.0f }, 0.5f }, // +Y plane + { { 0.0f, 1.0f, 0.0f }, 0.5f }, // -Y plane + { { 0.0f, 0.0f, -1.0f }, 0.5f }, // +Z plane + { { 0.0f, 0.0f, 1.0f }, 0.5f } // -Z Plane + } ); +} + +bool ClipPlanes::isOutside( const vmml::AABBf& worldBox ) const +{ + for( const auto& plane : getPlanes() ) + { + const float* normal = plane.getNormal(); + if( worldBox.isInFront( { normal[ 0 ], normal[ 1 ], normal[ 2 ], plane.getD() } )) + return true; + } + + return false; +} + +} +} diff --git a/lexis/render/ClipPlanes.h b/lexis/render/ClipPlanes.h new file mode 100644 index 0000000..2ae13f2 --- /dev/null +++ b/lexis/render/ClipPlanes.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2016-2017, Human Brain Project + * Ahmet.Bilgili@epfl.ch + */ + +#pragma once + +#include +#include +#include + +namespace lexis +{ +namespace render +{ + +class ClipPlanes : public detail::ClipPlanes +{ +public: + /** + * Adds 6 othogonal planes in normalized space (+x,-x,+y,-y,+z,-z). Convex + * region is defined as an AABB (-0.5,-0.5,-0.5) to (0.5, 0.5, 0.5). + */ + LEXIS_API ClipPlanes(); + + /** @return true if there are no clipping planes. */ + LEXIS_API bool isEmpty() const; + + /** Clears all planes, results in isEmpty() == true. */ + LEXIS_API void clear(); + + /** Reset to planes setup by constructor. */ + LEXIS_API void reset(); + + /** @return true if the box is outside the clip planes, aka shall be clipped.*/ + LEXIS_API bool isOutside( const vmml::AABBf& box ) const; +}; + +} +} diff --git a/lexis/render/Histogram.cpp b/lexis/render/Histogram.cpp new file mode 100644 index 0000000..6ba4f37 --- /dev/null +++ b/lexis/render/Histogram.cpp @@ -0,0 +1,104 @@ +/* Copyright (c) 2016-2017, Human Brain Project + * Ahmet.Bilgili@epfl.ch + */ + +#include "Histogram.h" + +#include + +namespace lexis +{ +namespace render +{ + +Histogram::Histogram() +{ + setMin( std::numeric_limits::infinity( )); + setMax( -std::numeric_limits::infinity( )); +} + +Histogram& Histogram::operator+=( const Histogram& histogram ) +{ + if( histogram.getBins().empty( )) + return *this; + + if( getBins().empty( )) + { + *this = histogram; + return *this; + } + + if( histogram.getBins().size() != getBins().size() || + histogram.getMin() != getMin() || + histogram.getMax() != getMax( )) + { + throw std::runtime_error( "Addition of incompatible histograms" ); + } + + const uint64_t* srcBins = histogram.getBins().data(); + + uint64_t* bins = getBins().data(); + for( size_t i = 0; i < getBins().size(); ++i ) + bins[ i ] += srcBins[ i ]; + + return *this; +} + +size_t Histogram::getMinIndex() const +{ + const uint64_t* bins = getBins().data(); + return std::distance( bins, std::min_element( bins, bins + getBins().size( ))); +} + +size_t Histogram::getMaxIndex() const +{ + const uint64_t* bins = getBins().data(); + return std::distance( bins, std::max_element( bins, bins + getBins().size( ))); +} + +bool Histogram::isEmpty() const +{ + const uint64_t* bins = getBins().data(); + for( size_t i = 0; i < getBins().size(); ++i ) + { + if( bins[ i ] > 0 ) + return false; + } + return true; +} + +uint64_t Histogram::getSum() const +{ + const uint64_t* bins = getBins().data(); + uint64_t sum = 0; + for( size_t i = 0; i < getBins().size(); ++i ) + sum += bins[ i ]; + + return sum; +} + +vmml::Vector2f Histogram::getRange() const +{ + return { getMin(), getMax() }; +} + +double Histogram::getRatio( const size_t index ) const +{ + if( index >= getBins().size( )) + return 0.0f; + + const uint64_t sum = getSum(); + if( sum == 0 ) + return 0.0f; + + const uint64_t* bins = getBins().data(); + return (double)bins[ index ] / (double)sum; +} + +void Histogram::resize( size_t newSize ) +{ + getBins().resize( newSize ); +} + +} +} diff --git a/lexis/render/Histogram.h b/lexis/render/Histogram.h new file mode 100644 index 0000000..e0363cb --- /dev/null +++ b/lexis/render/Histogram.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2016-2017, Human Brain Project + * Ahmet.Bilgili@epfl.ch + */ + +#pragma once + +#include +#include // base class +#include + +namespace lexis +{ +namespace render +{ + +class Histogram : public detail::Histogram +{ +public: + /** The minimum value is set to -inf and maximum value is set to -inf. */ + LEXIS_API Histogram(); + + /** + * Computes the addition of two histograms and modifies the object. + * + * If the histogram is empty this operator behaves the same as the + * assignment operator. + * @param histogram is the histogram to add + * @return the modified histogram + */ + LEXIS_API Histogram& operator+=( const Histogram& histogram ); + + /** + * @return the index with the minimum value (if there are multiple indices + * for min value, the smallest index is returned). + */ + LEXIS_API size_t getMinIndex() const; + + /** + * @return the index with the maximum value (if there are multiple indices + * for max value, the smallest index is returned). + */ + LEXIS_API size_t getMaxIndex() const; + + /** @return true if histogram has no values. */ + LEXIS_API bool isEmpty() const; + + /** @return the sum of the histogram. */ + LEXIS_API uint64_t getSum() const; + + /** @return the data range of the histogram. */ + LEXIS_API vmml::Vector2f getRange() const; + + /** + * Computes the ratio of the value at a given index. + * + * @param index the index of the histogram value + * @return the ratio at given index. If histogram is empty or index exceeds + * the histogram bin count, returns 0.0. + */ + LEXIS_API double getRatio( size_t index ) const; + + /** Sets the number of bins to newSize and clears the histogram. */ + LEXIS_API void resize( size_t newSize ); +}; + +} +} diff --git a/lexis/render/clipPlanes.fbs b/lexis/render/clipPlanes.fbs index 5c3e2a8..0323062 100644 --- a/lexis/render/clipPlanes.fbs +++ b/lexis/render/clipPlanes.fbs @@ -8,7 +8,7 @@ // is satisfied. If n.p + d < 0, these points are clipped. // The plane equations are defined in world reference system. -namespace lexis.render; +namespace lexis.render.detail; table Plane { diff --git a/lexis/render/histogram.fbs b/lexis/render/histogram.fbs index a08f92f..298f6ec 100644 --- a/lexis/render/histogram.fbs +++ b/lexis/render/histogram.fbs @@ -11,7 +11,7 @@ // bin value with the number of elements. // -namespace lexis.render; +namespace lexis.render.detail; table Histogram { diff --git a/tests/render/clipPlanes.cpp b/tests/render/clipPlanes.cpp new file mode 100644 index 0000000..a6e8554 --- /dev/null +++ b/tests/render/clipPlanes.cpp @@ -0,0 +1,41 @@ +/* Copyright (c) 2016-2017, Human Brain Project + * Ahmet.Bilgili@epfl.ch + */ + +#define BOOST_TEST_MODULE ClipPlanes + +#include +#include +#include + +BOOST_AUTO_TEST_CASE( testClipping ) +{ + // The default clipping planes include space defined by AABB + // ( -0.5, -0.5, -0.5 ) to ( 0.5, 0.5, 0.5 ) + + const vmml::Vector3f cornerOut1( 0.8f, 0.8f, 0.8f ); + const vmml::Vector3f cornerOut2( 0.9f, 0.9f, 0.9f ); + const vmml::Vector3f cornerIn1( -0.3f, -0.3f, -0.3f ); + const vmml::Vector3f cornerIn2( 0.3f, 0.3f, 0.3f ); + + const vmml::AABBf boxInside( cornerIn1, cornerIn2 ); + const vmml::AABBf boxOutside( cornerOut1, cornerOut2 ); + const vmml::AABBf boxIntersect( cornerIn1, cornerOut2 ); + + lexis::render::ClipPlanes clipPlanes; + + BOOST_CHECK( !clipPlanes.isOutside( boxInside )); + BOOST_CHECK( clipPlanes.isOutside( boxOutside )); + BOOST_CHECK( !clipPlanes.isOutside( boxIntersect )); + + BOOST_CHECK( !clipPlanes.isEmpty( )); + clipPlanes.clear(); + BOOST_CHECK( clipPlanes.isEmpty( )); + + clipPlanes.reset(); + BOOST_CHECK( !clipPlanes.isEmpty( )); + + BOOST_CHECK( !clipPlanes.isOutside( boxInside )); + BOOST_CHECK( clipPlanes.isOutside( boxOutside )); + BOOST_CHECK( !clipPlanes.isOutside( boxIntersect )); +}