<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include <iostream>
#include <limits>
#include <stdexcept>
#include <type_traits>

#include "itkCastImageFilter.h"
#include "itkRandomImageSource.h"
#include "itkVectorImage.h"
#include "itkFloatingPointExceptions.h"

// Better name demanging for gcc
#if defined( __GNUC__ ) && !defined( __EMSCRIPTEN__ )
#define GCC_USEDEMANGLE
#endif

#ifdef GCC_USEDEMANGLE
#include <cstdlib>
#include <cxxabi.h>
#include "itkMath.h"
#endif

template< typename T >
std::string GetCastTypeName()
{
  std::string name;
#ifdef GCC_USEDEMANGLE
  char const *mangledName = typeid( T ).name();
  int         status;
  char *      unmangled = abi::__cxa_demangle(mangledName, nullptr, nullptr, &status);
  name = unmangled;
  free(unmangled);
#else
  name = typeid( T ).name();
#endif

  return name;
}

// A reference defining C++ behavior:
// http://www.cplusplus.com/doc/tutorial/typecasting/
// static_cast_is_well_defined function returns true if the result of the static cast is well defined
// and false if the result is undefined.
template <typename TInput, typename TOutput>
static typename std::enable_if<std::is_integral<TOutput>::value
                            && std::is_integral<TInput>::value, bool>::type
static_cast_is_well_defined(TInput ) {
  return true; // casting from int to int types employes deterministic 2's complement behavior
}

template <typename TInput, typename TOutput>
static typename std::enable_if<std::is_floating_point<TOutput>::value
                            && ( std::is_floating_point<TInput>::value || std::is_integral<TInput>::value ), bool>::type
static_cast_is_well_defined(TInput ) {
  return true; //Floating point to floating point static casts are always consistently defined.
}

template <typename TInput, typename TOutput>
static typename std::enable_if<std::is_integral<TOutput>::value && std::is_unsigned<TOutput>::value
                            && std::is_floating_point<TInput>::value, bool>::type
static_cast_is_well_defined(TInput value) {
  if (value < 0.0 || value > static_cast<TInput>( std::numeric_limits<TOutput>::max() )) {
    return false;
  }
  return true;
}

template <typename TInput, typename TOutput>
static typename std::enable_if<std::is_integral<TOutput>::value && std::is_signed<TOutput>::value
                            && std::is_floating_point<TInput>::value, bool>::type
static_cast_is_well_defined(TInput value) {
  if (value < static_cast<TInput>( std::numeric_limits<TOutput>::min() )
    || value > static_cast<TInput>( std::numeric_limits<TOutput>::max() )) {
    return false;
  }
  return true;
}

template < typename TInputPixelType, typename TOutputPixelType >
bool TestCastFromTo()
{
  using InputImageType = itk::Image< TInputPixelType, 3 >;
  using OutputImageType = itk::Image< TOutputPixelType, 3 >;
  using FilterType = itk::CastImageFilter< InputImageType, OutputImageType >;

  using SourceType = itk::RandomImageSource< InputImageType >;
  typename SourceType::Pointer randomValuesImageSource = SourceType::New();
  {
    typename InputImageType::SizeValueType randomSize[3] = {18, 17, 23};
    randomValuesImageSource->SetSize(randomSize);
  }
  randomValuesImageSource->UpdateLargestPossibleRegion();
  typename InputImageType::Pointer randomSourceImagePtr = randomValuesImageSource->GetOutput();
  {
    typename InputImageType::IndexType Index000{{0,0,0}};
    typename InputImageType::IndexType Index100{{1,0,0}};
    typename InputImageType::IndexType Index200{{2,0,0}};
    typename InputImageType::IndexType Index300{{3,0,0}};
    typename InputImageType::IndexType Index400{{4,0,0}};

    /* Exercise input image type domain values (important for float -> integer conversions)
     *
     * Casting a float/double to an integer when integer isn't big enough to hold the value yields undefined behaviour.
     *
     * [n3290: 4.9/1]: A prvalue of a floating point type can be converted to a prvalue of an integer type.
     *  The conversion truncates; that is, the fractional part is discarded.
     *
     *  The behavior is undefined if the truncated value cannot be represented in the destination type.
     *                  ^^^^^^^^^
     * With scanline based optimization, SSE instructions can be used for converting blocks of
     * floats to integer, which results in different 'undefined' behavior for values
     * than an isolated static_cast<short>(outOfRangeFloat).
    */
    randomSourceImagePtr->SetPixel(Index000, std::numeric_limits<TInputPixelType>::max());
    randomSourceImagePtr->SetPixel(Index100, std::numeric_limits<TInputPixelType>::min());
    randomSourceImagePtr->SetPixel(Index200, std::numeric_limits<TInputPixelType>::epsilon() );
    randomSourceImagePtr->SetPixel(Index300, std::numeric_limits<TInputPixelType>::denorm_min() );
    randomSourceImagePtr->SetPixel(Index400, std::numeric_limits<TInputPixelType>::round_error() );
  }

  typename FilterType::Pointer filter = FilterType::New();
  filter->SetInput( randomSourceImagePtr );
  filter->UpdateLargestPossibleRegion();

  using InputIteratorType = itk::ImageRegionConstIterator< InputImageType >;
  using OutputIteratorType = itk::ImageRegionConstIterator< OutputImageType >;

  InputIteratorType  it( randomValuesImageSource->GetOutput(),
                         randomValuesImageSource->GetOutput()->GetLargestPossibleRegion() );
  OutputIteratorType ot( filter->GetOutput(),
                         filter->GetOutput()->GetLargestPossibleRegion() );

  bool success = true;

  std::cout << "Casting from " << GetCastTypeName< TInputPixelType >()
            << " to " << GetCastTypeName< TOutputPixelType >() << " ... ";

  it.GoToBegin();
  ot.GoToBegin();
  while ( !it.IsAtEnd() )
    {
    const TInputPixelType  inValue  = it.Value();
    const TOutputPixelType outValue = ot.Value();
    const auto expectedValue = static_cast< TOutputPixelType >( inValue );

    if ( ! static_cast_is_well_defined<TInputPixelType,TOutputPixelType> ( inValue ) )
    {
      ++it;
      ++ot;
      std::cout << std::flush;
      //Debugging code left here for testing __MINGW32__ behavior below that may be redundant with this code
      //std::cout << "NOTICE: static_cast<" << GetCastTypeName< TOutputPixelType >() << ">(" << inValue << ") => "
      //         << outValue << " may not equal " << expectedValue
      //         << "  Casting out of range floating point values to integers is 'undefined' behavior."
      //         << std::flush << std::endl;
      continue;  // Simply skip the case where where the conversion is undefined.
    }

    /** Warning:
     * expectedValue == static_cast< TOutputPixelType( inValue ) is
     * false on some systems and compilers with some values of inValue. */
#if defined(__MINGW32__)  // NOTE:  This may be the same problem identified above related to 'undefined' behavior
    if ( itk::Math::NotAlmostEquals(outValue, expectedValue) )
#else
    if ( itk::Math::NotExactlyEquals(outValue, expectedValue) )
#endif
      {
      std::cout << std::flush;
      std::cerr << "ERROR: staic_cast<" << GetCastTypeName< TOutputPixelType >() << ">(" << inValue << ") => "
                << outValue << " != " << expectedValue << std::flush << std::endl;
      success = false;
      break;
      }

    ++it;
    ++ot;
    }

  if ( success )
    {
    std::cout << "[PASSED]" << std::endl;
    }
  else
    {
    std::cout << "[FAILED]" << std::endl;
    }

  return success;
}

template < typename TInputPixelType >
bool TestCastFrom()
{
  bool success = true;
  success &= TestCastFromTo< TInputPixelType, char >();
  success &= TestCastFromTo< TInputPixelType, signed char >();
  success &= TestCastFromTo< TInputPixelType, unsigned char >();
  success &= TestCastFromTo< TInputPixelType, short >();
  success &= TestCastFromTo< TInputPixelType, unsigned short >();
  success &= TestCastFromTo< TInputPixelType, int >();
  success &= TestCastFromTo< TInputPixelType, unsigned int >();
  success &= TestCastFromTo< TInputPixelType, long >();
  success &= TestCastFromTo< TInputPixelType, unsigned long >();
  success &= TestCastFromTo< TInputPixelType, long long >();
  success &= TestCastFromTo< TInputPixelType, unsigned long long >();
  success &= TestCastFromTo< TInputPixelType, float >();
  success &= TestCastFromTo< TInputPixelType, double >();

  return success;
}

bool TestVectorImageCast()
{
  // This function casts a VectorImage<float, 2>
  // to a VectorImage<unsigned char, 2>
  std::cout << "Casting from a VectorImage<float, 2> \
                to VectorImage<unsigned char, 2> ..." << std::endl;

  using UnsignedCharVectorImageType = itk::VectorImage<unsigned char, 2>;
  using FloatVectorImageType = itk::VectorImage<float, 2>;

  // Create a 1x3 image of 2D vectors
  FloatVectorImageType::Pointer image = FloatVectorImageType::New();

  const itk::Size<2> size{ { 1, 3 } };
  const itk::Index<2> start{ { 0, 0 } };

  itk::ImageRegion<2> region(start,size);
  image->SetNumberOfComponentsPerPixel(2);
  image->SetRegions(region);
  image->Allocate();
  itk::VariableLengthVector<float> vec;
  vec.SetSize(2);
  // All pixels will be the vector (1.3, 5.3)
  vec[0] = 1.3;
  vec[1] = 5.3;
  image->FillBuffer(vec);

  using CastImageFilterType = itk::CastImageFilter< FloatVectorImageType,
               UnsignedCharVectorImageType >;
  CastImageFilterType::Pointer castImageFilter = CastImageFilterType::New();
  castImageFilter->SetInput(image);
  castImageFilter->Update();

  // Setup iterators for the original and casted images
  itk::ImageRegionConstIterator<UnsignedCharVectorImageType>
       castedImageIterator(castImageFilter->GetOutput(),
       castImageFilter->GetOutput()->GetLargestPossibleRegion());

  itk::ImageRegionConstIterator<FloatVectorImageType>
    originalImageIterator(image, image->GetLargestPossibleRegion());

  // Compare both dimensions of all of the pixels from the manually
  // casted original image to the corresponding pixels in the filter-casted
  // image
  bool success = true;
  while(!originalImageIterator.IsAtEnd())
    {
    if(static_cast<unsigned char>(originalImageIterator.Get()[0]) !=
                                  castedImageIterator.Get()[0] ||
       static_cast<unsigned char>(originalImageIterator.Get()[1]) !=
                                  castedImageIterator.Get()[1])
      {
      std::cerr << "Error in TestVectorImageCast!" << std::endl;
      success = false;
      }
    ++originalImageIterator;
    ++castedImageIterator;
    }

  if ( success )
    {
    std::cout << "[PASSED]" << std::endl;
    }
  else
    {
    std::cout << "[FAILED]" << std::endl;
    }

  return success;
}

int itkCastImageFilterTest( int, char* [] )
{
  std::cout << "itkCastImageFilterTest Start" << std::endl;

  // This test casts floats to char, generating float point exceptions.
  // We disable float point exceptions only for this tests
  bool fpeSupport = itk::FloatingPointExceptions::HasFloatingPointExceptionsSupport();
  bool fpeStatus = itk::FloatingPointExceptions::GetEnabled();
  if (fpeSupport && fpeStatus)
    {
    std::cout << "FloatingPointExceptions are disabled only for this test." << std::endl;
    itk::FloatingPointExceptions::Disable();
    }

  bool success = true;
  success &= TestCastFrom< char >();
  success &= TestCastFrom< signed char >();
  success &= TestCastFrom< unsigned char >();
  success &= TestCastFrom< short >();
  success &= TestCastFrom< unsigned short >();
  success &= TestCastFrom< int >();
  success &= TestCastFrom< unsigned int >();
  success &= TestCastFrom< long >();
  success &= TestCastFrom< unsigned long >();
  success &= TestCastFrom< long long >();
  success &= TestCastFrom< unsigned long long >();
  success &= TestCastFrom< float >();
  success &= TestCastFrom< double >();
  success &= TestVectorImageCast();

  std::cout << std::endl;
  if ( !success )
    {
    std::cout << "An itkCastImageFilter test FAILED." << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "All itkCastImageFilter tests PASSED." << std::endl;

  return EXIT_SUCCESS;
}
<commit_msg>ENH: Add testing for CastImageFilter for more type conversions<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include <iostream>
#include <limits>
#include <stdexcept>
#include <type_traits>

#include "itkCastImageFilter.h"
#include "itkRandomImageSource.h"
#include "itkVectorImage.h"
#include "itkFloatingPointExceptions.h"
#include "itkRGBPixel.h"
#include "itkRGBAPixel.h"

// Better name demanging for gcc
#if defined( __GNUC__ ) && !defined( __EMSCRIPTEN__ )
#define GCC_USEDEMANGLE
#endif

#ifdef GCC_USEDEMANGLE
#include <cstdlib>
#include <cxxabi.h>
#include "itkMath.h"
#endif

// Compile time check
template class itk::CastImageFilter<itk::Image<std::complex<float> >, itk::Image<std::complex<float> > >;
template class itk::CastImageFilter<itk::Image<std::complex<double> >, itk::Image<std::complex<double> > >;
template class itk::CastImageFilter<itk::Image<std::complex<float> >, itk::Image<std::complex<double> > >;

template class itk::CastImageFilter<itk::Image<itk::RGBPixel<unsigned char> >, itk::Image<itk::RGBPixel<unsigned short> > >;
template class itk::CastImageFilter<itk::Image<itk::RGBPixel<unsigned char> >, itk::Image<itk::Vector<float,3> > >;
template class itk::CastImageFilter<itk::Image<itk::Vector<float,3> >, itk::Image<itk::RGBPixel<unsigned char> > >;
template class itk::CastImageFilter<itk::Image<itk::RGBAPixel<unsigned char> >, itk::Image<itk::RGBAPixel<unsigned short> > >;
template class itk::CastImageFilter<itk::Image<itk::RGBAPixel<unsigned char> >, itk::Image<itk::Vector<float,4> > >;
template class itk::CastImageFilter<itk::Image<itk::Vector<float,4> >, itk::Image<itk::RGBAPixel<unsigned char> > >;

template class itk::CastImageFilter<itk::VectorImage<short>, itk::VectorImage<double> >;

template< typename T >
std::string GetCastTypeName()
{
  std::string name;
#ifdef GCC_USEDEMANGLE
  char const *mangledName = typeid( T ).name();
  int         status;
  char *      unmangled = abi::__cxa_demangle(mangledName, nullptr, nullptr, &status);
  name = unmangled;
  free(unmangled);
#else
  name = typeid( T ).name();
#endif

  return name;
}

// A reference defining C++ behavior:
// http://www.cplusplus.com/doc/tutorial/typecasting/
// static_cast_is_well_defined function returns true if the result of the static cast is well defined
// and false if the result is undefined.
template <typename TInput, typename TOutput>
static typename std::enable_if<std::is_integral<TOutput>::value
                            && std::is_integral<TInput>::value, bool>::type
static_cast_is_well_defined(TInput ) {
  return true; // casting from int to int types employes deterministic 2's complement behavior
}

template <typename TInput, typename TOutput>
static typename std::enable_if<std::is_floating_point<TOutput>::value
                            && ( std::is_floating_point<TInput>::value || std::is_integral<TInput>::value ), bool>::type
static_cast_is_well_defined(TInput ) {
  return true; //Floating point to floating point static casts are always consistently defined.
}

template <typename TInput, typename TOutput>
static typename std::enable_if<std::is_integral<TOutput>::value && std::is_unsigned<TOutput>::value
                            && std::is_floating_point<TInput>::value, bool>::type
static_cast_is_well_defined(TInput value) {
  if (value < 0.0 || value > static_cast<TInput>( std::numeric_limits<TOutput>::max() )) {
    return false;
  }
  return true;
}

template <typename TInput, typename TOutput>
static typename std::enable_if<std::is_integral<TOutput>::value && std::is_signed<TOutput>::value
                            && std::is_floating_point<TInput>::value, bool>::type
static_cast_is_well_defined(TInput value) {
  if (value < static_cast<TInput>( std::numeric_limits<TOutput>::min() )
    || value > static_cast<TInput>( std::numeric_limits<TOutput>::max() )) {
    return false;
  }
  return true;
}

template < typename TInputPixelType, typename TOutputPixelType >
bool TestCastFromTo()
{
  using InputImageType = itk::Image< TInputPixelType, 3 >;
  using OutputImageType = itk::Image< TOutputPixelType, 3 >;
  using FilterType = itk::CastImageFilter< InputImageType, OutputImageType >;

  using SourceType = itk::RandomImageSource< InputImageType >;
  typename SourceType::Pointer randomValuesImageSource = SourceType::New();
  {
    typename InputImageType::SizeValueType randomSize[3] = {18, 17, 23};
    randomValuesImageSource->SetSize(randomSize);
  }
  randomValuesImageSource->UpdateLargestPossibleRegion();
  typename InputImageType::Pointer randomSourceImagePtr = randomValuesImageSource->GetOutput();
  {
    typename InputImageType::IndexType Index000{{0,0,0}};
    typename InputImageType::IndexType Index100{{1,0,0}};
    typename InputImageType::IndexType Index200{{2,0,0}};
    typename InputImageType::IndexType Index300{{3,0,0}};
    typename InputImageType::IndexType Index400{{4,0,0}};

    /* Exercise input image type domain values (important for float -> integer conversions)
     *
     * Casting a float/double to an integer when integer isn't big enough to hold the value yields undefined behaviour.
     *
     * [n3290: 4.9/1]: A prvalue of a floating point type can be converted to a prvalue of an integer type.
     *  The conversion truncates; that is, the fractional part is discarded.
     *
     *  The behavior is undefined if the truncated value cannot be represented in the destination type.
     *                  ^^^^^^^^^
     * With scanline based optimization, SSE instructions can be used for converting blocks of
     * floats to integer, which results in different 'undefined' behavior for values
     * than an isolated static_cast<short>(outOfRangeFloat).
    */
    randomSourceImagePtr->SetPixel(Index000, std::numeric_limits<TInputPixelType>::max());
    randomSourceImagePtr->SetPixel(Index100, std::numeric_limits<TInputPixelType>::min());
    randomSourceImagePtr->SetPixel(Index200, std::numeric_limits<TInputPixelType>::epsilon() );
    randomSourceImagePtr->SetPixel(Index300, std::numeric_limits<TInputPixelType>::denorm_min() );
    randomSourceImagePtr->SetPixel(Index400, std::numeric_limits<TInputPixelType>::round_error() );
  }

  typename FilterType::Pointer filter = FilterType::New();
  filter->SetInput( randomSourceImagePtr );
  filter->UpdateLargestPossibleRegion();

  using InputIteratorType = itk::ImageRegionConstIterator< InputImageType >;
  using OutputIteratorType = itk::ImageRegionConstIterator< OutputImageType >;

  InputIteratorType  it( randomValuesImageSource->GetOutput(),
                         randomValuesImageSource->GetOutput()->GetLargestPossibleRegion() );
  OutputIteratorType ot( filter->GetOutput(),
                         filter->GetOutput()->GetLargestPossibleRegion() );

  bool success = true;

  std::cout << "Casting from " << GetCastTypeName< TInputPixelType >()
            << " to " << GetCastTypeName< TOutputPixelType >() << " ... ";

  it.GoToBegin();
  ot.GoToBegin();
  while ( !it.IsAtEnd() )
    {
    const TInputPixelType  inValue  = it.Value();
    const TOutputPixelType outValue = ot.Value();
    const auto expectedValue = static_cast< TOutputPixelType >( inValue );

    if ( ! static_cast_is_well_defined<TInputPixelType,TOutputPixelType> ( inValue ) )
    {
      ++it;
      ++ot;
      std::cout << std::flush;
      //Debugging code left here for testing __MINGW32__ behavior below that may be redundant with this code
      //std::cout << "NOTICE: static_cast<" << GetCastTypeName< TOutputPixelType >() << ">(" << inValue << ") => "
      //         << outValue << " may not equal " << expectedValue
      //         << "  Casting out of range floating point values to integers is 'undefined' behavior."
      //         << std::flush << std::endl;
      continue;  // Simply skip the case where where the conversion is undefined.
    }

    /** Warning:
     * expectedValue == static_cast< TOutputPixelType( inValue ) is
     * false on some systems and compilers with some values of inValue. */
#if defined(__MINGW32__)  // NOTE:  This may be the same problem identified above related to 'undefined' behavior
    if ( itk::Math::NotAlmostEquals(outValue, expectedValue) )
#else
    if ( itk::Math::NotExactlyEquals(outValue, expectedValue) )
#endif
      {
      std::cout << std::flush;
      std::cerr << "ERROR: staic_cast<" << GetCastTypeName< TOutputPixelType >() << ">(" << inValue << ") => "
                << outValue << " != " << expectedValue << std::flush << std::endl;
      success = false;
      break;
      }

    ++it;
    ++ot;
    }

  if ( success )
    {
    std::cout << "[PASSED]" << std::endl;
    }
  else
    {
    std::cout << "[FAILED]" << std::endl;
    }

  return success;
}

template < typename TInputPixelType >
bool TestCastFrom()
{
  bool success = true;
  success &= TestCastFromTo< TInputPixelType, char >();
  success &= TestCastFromTo< TInputPixelType, signed char >();
  success &= TestCastFromTo< TInputPixelType, unsigned char >();
  success &= TestCastFromTo< TInputPixelType, short >();
  success &= TestCastFromTo< TInputPixelType, unsigned short >();
  success &= TestCastFromTo< TInputPixelType, int >();
  success &= TestCastFromTo< TInputPixelType, unsigned int >();
  success &= TestCastFromTo< TInputPixelType, long >();
  success &= TestCastFromTo< TInputPixelType, unsigned long >();
  success &= TestCastFromTo< TInputPixelType, long long >();
  success &= TestCastFromTo< TInputPixelType, unsigned long long >();
  success &= TestCastFromTo< TInputPixelType, float >();
  success &= TestCastFromTo< TInputPixelType, double >();

  return success;
}

bool TestVectorImageCast()
{
  // This function casts a VectorImage<float, 2>
  // to a VectorImage<unsigned char, 2>
  std::cout << "Casting from a VectorImage<float, 2> \
                to VectorImage<unsigned char, 2> ..." << std::endl;

  using UnsignedCharVectorImageType = itk::VectorImage<unsigned char, 2>;
  using FloatVectorImageType = itk::VectorImage<float, 2>;

  // Create a 1x3 image of 2D vectors
  FloatVectorImageType::Pointer image = FloatVectorImageType::New();

  const itk::Size<2> size{ { 1, 3 } };
  const itk::Index<2> start{ { 0, 0 } };

  itk::ImageRegion<2> region(start,size);
  image->SetNumberOfComponentsPerPixel(2);
  image->SetRegions(region);
  image->Allocate();
  itk::VariableLengthVector<float> vec;
  vec.SetSize(2);
  // All pixels will be the vector (1.3, 5.3)
  vec[0] = 1.3;
  vec[1] = 5.3;
  image->FillBuffer(vec);

  using CastImageFilterType = itk::CastImageFilter< FloatVectorImageType,
               UnsignedCharVectorImageType >;
  CastImageFilterType::Pointer castImageFilter = CastImageFilterType::New();
  castImageFilter->SetInput(image);
  castImageFilter->Update();

  // Setup iterators for the original and casted images
  itk::ImageRegionConstIterator<UnsignedCharVectorImageType>
       castedImageIterator(castImageFilter->GetOutput(),
       castImageFilter->GetOutput()->GetLargestPossibleRegion());

  itk::ImageRegionConstIterator<FloatVectorImageType>
    originalImageIterator(image, image->GetLargestPossibleRegion());

  // Compare both dimensions of all of the pixels from the manually
  // casted original image to the corresponding pixels in the filter-casted
  // image
  bool success = true;
  while(!originalImageIterator.IsAtEnd())
    {
    if(static_cast<unsigned char>(originalImageIterator.Get()[0]) !=
                                  castedImageIterator.Get()[0] ||
       static_cast<unsigned char>(originalImageIterator.Get()[1]) !=
                                  castedImageIterator.Get()[1])
      {
      std::cerr << "Error in TestVectorImageCast!" << std::endl;
      success = false;
      }
    ++originalImageIterator;
    ++castedImageIterator;
    }

  if ( success )
    {
    std::cout << "[PASSED]" << std::endl;
    }
  else
    {
    std::cout << "[FAILED]" << std::endl;
    }

  return success;
}

int itkCastImageFilterTest( int, char* [] )
{
  std::cout << "itkCastImageFilterTest Start" << std::endl;

  // This test casts floats to char, generating float point exceptions.
  // We disable float point exceptions only for this tests
  bool fpeSupport = itk::FloatingPointExceptions::HasFloatingPointExceptionsSupport();
  bool fpeStatus = itk::FloatingPointExceptions::GetEnabled();
  if (fpeSupport && fpeStatus)
    {
    std::cout << "FloatingPointExceptions are disabled only for this test." << std::endl;
    itk::FloatingPointExceptions::Disable();
    }

  bool success = true;
  success &= TestCastFrom< char >();
  success &= TestCastFrom< signed char >();
  success &= TestCastFrom< unsigned char >();
  success &= TestCastFrom< short >();
  success &= TestCastFrom< unsigned short >();
  success &= TestCastFrom< int >();
  success &= TestCastFrom< unsigned int >();
  success &= TestCastFrom< long >();
  success &= TestCastFrom< unsigned long >();
  success &= TestCastFrom< long long >();
  success &= TestCastFrom< unsigned long long >();
  success &= TestCastFrom< float >();
  success &= TestCastFrom< double >();
  success &= TestVectorImageCast();

  std::cout << std::endl;
  if ( !success )
    {
    std::cout << "An itkCastImageFilter test FAILED." << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "All itkCastImageFilter tests PASSED." << std::endl;

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*******************************************************************************

Quick sort
==============

Ref - http://quiz.geeksforgeeks.org/quick-sort/

--------------------------------------------------------------------------------

Problem
=======
Classic old quick sort.

--------------------------------------------------------------------------------

Time Complexity
===============
O(nlogn)

--------------------------------------------------------------------------------

Output
======
Array is initially:
64 34 25 12 22 11 90
After quick sort, array is:
11 12 22 25 34 64 90

*******************************************************************************/

#include <stdio.h>

void printArray(int arr[], int n) {
  for(int i = 0; i < n; ++i)
    printf("%d ", arr[i]);
  printf("\n");
}

void merge(int arr[], int l, int m, int r) {
  int n1 = m - l + 1;
  int n2 = r - m;

  int L[n1], R[n2];

  for (int i = 0; i < n1; i++) {
    L[i] = arr[l + i];
  }
  for (int i = 0; i < n2; i++) {
    R[i] = arr[m + i + 1];
  }

  int i = 0, j = 0, k = l;
  while (i < n1 && j < n2) {
    if (L[i] <= R[j]) {
      arr[k] = L[i++];
    }
    else  {
      arr[k] = R[j++];
    }
    k++;
  }

  while (i < n1) {
    arr[k++] = L[i++];
  }
  while (j < n2) {
    arr[k++] = R[j++];
  }
}

void swap(int *p, int *q) {
  int temp = *p;
  *p = *q;
  *q = temp;
}

int partition(int arr[], int l, int r)  {
  int pivot = arr[r];
  int i = l;
  for (int j = l; j < r; j++) {
    if (arr[j] <= pivot) {
      swap(&arr[i++], &arr[j]);
    }
  }
  swap(&arr[i], &arr[r]);
  return i;
}

void quickSort(int arr[], int l, int r) {
  if (l < r) {
    int p = partition(arr, l, r);

    quickSort(arr, l, p - 1);
    quickSort(arr, p + 1, r);
  }
}

int main()  {
  int arr[] = {64, 34, 25, 12, 22, 11, 90};
  printf("Array is initially:\n");
  printArray(arr, 7);
  printf("After quick sort, array is:\n");
  quickSort(arr, 0, 6);
  printArray(arr, 7);
  return 0;
}
<commit_msg>Modified quick sort<commit_after>/*******************************************************************************

Quick sort
==========

Ref - http://quiz.geeksforgeeks.org/quick-sort/

--------------------------------------------------------------------------------

Problem
=======
Classic old quick sort.

--------------------------------------------------------------------------------

Time Complexity
===============
O(nlogn)

--------------------------------------------------------------------------------

Output
======
Array is initially:
64 34 25 12 22 11 90
After quick sort, array is:
11 12 22 25 34 64 90

*******************************************************************************/

#include <stdio.h>

void printArray(int arr[], int n) {
  for(int i = 0; i < n; ++i)
    printf("%d ", arr[i]);
  printf("\n");
}

void swap(int *p, int *q) {
  int temp = *p;
  *p = *q;
  *q = temp;
}

int partition(int arr[], int l, int r)  {
  int pivot = arr[r];
  int i = l;
  for (int j = l; j < r; j++) {
    if (arr[j] <= pivot) {
      swap(&arr[i++], &arr[j]);
    }
  }
  swap(&arr[i], &arr[r]);
  return i;
}

void quickSort(int arr[], int l, int r) {
  if (l < r) {
    int p = partition(arr, l, r);

    quickSort(arr, l, p - 1);
    quickSort(arr, p + 1, r);
  }
}

int main()  {
  int arr[] = {64, 34, 25, 12, 22, 11, 90};
  printf("Array is initially:\n");
  printArray(arr, 7);
  printf("After quick sort, array is:\n");
  quickSort(arr, 0, 6);
  printArray(arr, 7);
  return 0;
}
<|endoftext|>


<commit_before><commit_msg>Update MusicPlayer.cpp<commit_after>#include "MusicPlayer.h"

std::wstring s2ws(const std::string& s)
{
	int len;
	int slength = (int)s.length() + 1;
	len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
	wchar_t* buf = new wchar_t[len];
	MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
	std::wstring r(buf);
	delete[] buf;
	return r;
}
int main(int argc, char* argv[]){
	//Change this string to whatever file you want to test
	string locationOfMusic = "C:\\Users\\nc1\\Downloads\\Boombox_Cartel_-_Dia_De_Los_Muertos_Mix.mp3";
	//Placeholder menu for gui buttons
	while(playerIsOpen){
		cout << "Media Controls" << endl;
		cout << "1. Play" << endl;
		cout << "2. Pause" << endl;
		cout << "3. Resume" << endl;
		cout << "4. Stop" << endl << endl;
		int choice;
		cin >> choice;
		switch(choice){
			case 1://Play
				//if(!isPlaying){
					Play(locationOfMusic);
				//}
				break;
			case 2://Pause
				if(isPlaying){
					Pause(locationOfMusic);
				}
				break;
			case 3://Resume
				if(!isPlaying) Resume(locationOfMusic);
				break;
			case 4://Stop
				Stop(locationOfMusic);
				break;
			default:
				playerIsOpen = false;
				break;
		}

	}

}
MusicPlayer::MusicPlayer(){
	playerIsOpen = true;
	isOpen = false;
	isPlaying = false;
}
//Opens and plays a new song given a filepath input
void MusicPlayer::Play(string filePath){
	ostringstream os;
	//L"open \" + file path and name + \"....
	os << "open \"" << filePath << "\" type MPEGvideo alias song";
	LPCWSTR a = s2ws(os.str().c_str());
	mciSendStringW(a, NULL, 0, NULL);
	//Play the song
	mciSendString("Play " + filePath, NULL, 0, NULL);
	isOpen = true;
}
//Pauses a song at filepath input
void MusicPlayer::Pause(string filePath){
	mciSendString("Pause " + filePath, NULL, 0, NULL);
	isPlaying = false;
}
//Resumes a song at filepath input
void MusicPlayer::Resume(string filePath){
	mciSendString("Resume " + filePath, NULL, 0, NULL);
	isPlaying = true;
}
//Closes a song at filepath input
void MusicPlayer::Stop(string filePath){
	if(isOpen){
		mciSendString("Close " + filePath, NULL, 0, NULL);
		isOpen = false;
	}
}
//To change songs, pause current, close current, open next/previous, play next/previous
<|endoftext|>


<commit_before>/*
 * Executor.cpp
 *
 *  Created on: Oct 20, 2015
 *      Author: Péter Fankhauser
 *   Institute: ETH Zurich, Autonomous Systems Lab
 */

#include "free_gait_core/executor/Executor.hpp"

#include <robotUtils/timers/ChronoTimer.hpp>

namespace free_gait {

Executor::Executor(std::shared_ptr<StepCompleter> completer,
                   std::shared_ptr<AdapterBase> adapter,
                   std::shared_ptr<State> state)
    : completer_(completer),
      adapter_(adapter),
      state_(state),
      isInitialized_(false)
{
}

Executor::~Executor()
{
}

bool Executor::initialize()
{
  Lock lock(mutex_);
  state_->initialize(adapter_->getLimbs(), adapter_->getBranches());
  reset();
  return isInitialized_ = true;
}

bool Executor::isInitialized() const
{
  return isInitialized_;
}

Executor::Mutex& Executor::getMutex()
{
  return mutex_;
}

bool Executor::advance(double dt)
{
  Lock lock(mutex_);

  if (!isInitialized_) return false;
  updateStateWithMeasurements();

  if (checkRobotStatus()) {
    if (!state_->getRobotExecutionStatus()) std::cout << "Continuing with free gait execution." << std::endl;
    state_->setRobotExecutionStatus(true);
  } else {
    if (state_->getRobotExecutionStatus()) std::cout << "Robot status is not OK, not continuing with free gait execution." << std::endl;
    state_->setRobotExecutionStatus(false);
    return true;
  }

  bool hasSwitchedStep;
  if (!queue_.advance(dt, hasSwitchedStep)) return false;

  while (hasSwitchedStep) {

    if (!queue_.getCurrentStep().requiresMultiThreading()) {
      if (!completeCurrentStep()) return false;
      if (!queue_.advance(dt, hasSwitchedStep)) return false; // Advance again after completion.
    } else {
      std::thread thread(&Executor::completeCurrentStep, this);
      thread.detach();
      hasSwitchedStep = false;
    }
  }

  if (!writeIgnoreContact()) return false;
  if (!writeIgnoreForPoseAdaptation()) return false;
  if (!writeSupportLegs()) return false;
  if (!writeSurfaceNormals()) return false;
  if (!writeLegMotion()) return false;
  if (!writeTorsoMotion()) return false;
  if (!adapter_->updateExtras(queue_, *state_)) return false;
//  std::cout << *state_ << std::endl;
  return true;
}

bool Executor::completeCurrentStep()
{
  robotUtils::ChronoTimer timer;
  timer.pinTime();

//  if (queue_.getCurrentStep().requiresMultiThreading()) {
//    std::cout << "Taking a break." << std::endl;
//    std::this_thread::sleep_for(std::chrono::seconds(10));
//    std::cout << "Finished break." << std::endl;
//  }

  if (!completer_->complete(*state_, queue_, queue_.getCurrentStep())) {
    std::cerr << "Executor::advance: Could not complete step." << std::endl;
    return false;
  }

  std::cout << "Time to compute step: " << timer.getElapsedTimeMsec() << std::endl;
  std::cout << "Switched step to:" << std::endl;
  std::cout << queue_.getCurrentStep() << std::endl;
  return true;
}

void Executor::reset()
{
  Lock lock(mutex_);
  queue_.clear();
  initializeStateWithRobot();
}

const StepQueue& Executor::getQueue() const
{
  return queue_;
}

StepQueue& Executor::getQueue()
{
  return queue_;
}

const State& Executor::getState() const
{
  return *state_;
}

const AdapterBase& Executor::getAdapter() const
{
  return *adapter_;
}

bool Executor::checkRobotStatus()
{
  for (const auto& limb : adapter_->getLimbs()) {
    if (state_->isSupportLeg(limb) && !adapter_->isLegGrounded(limb)) return false;
  }
  return true;
}

bool Executor::initializeStateWithRobot()
{
  for (const auto& limb : adapter_->getLimbs()) {
    state_->setSupportLeg(limb, adapter_->isLegGrounded(limb));
    state_->setIgnoreContact(limb, !adapter_->isLegGrounded(limb));
    state_->setIgnoreForPoseAdaptation(limb, !adapter_->isLegGrounded(limb));
    state_->removeSurfaceNormal(limb);
  }

  if (state_->getNumberOfSupportLegs() > 0) {
    state_->setControlSetup(BranchEnum::BASE, adapter_->getControlSetup(BranchEnum::BASE));
  } else {
    state_->setEmptyControlSetup(BranchEnum::BASE);
  }

  for (const auto& limb : adapter_->getLimbs()) {
    if (state_->isSupportLeg(limb)) {
      state_->setEmptyControlSetup(limb);
    } else {
      state_->setControlSetup(limb, adapter_->getControlSetup(limb));
    }
  }

  state_->setAllJointPositions(adapter_->getAllJointPositions());
  state_->setAllJointVelocities(adapter_->getAllJointVelocities());
//  state_->setAllJointAccelerations(adapter_->getAllJointAccelerations()); // TODO
  state_->setAllJointEfforts(adapter_->getAllJointEfforts());
  state_->setPositionWorldToBaseInWorldFrame(adapter_->getPositionWorldToBaseInWorldFrame());
  state_->setOrientationWorldToBase(adapter_->getOrientationWorldToBase());

  for (const auto& limb : adapter_->getLimbs()) {
    state_->setSupportLeg(limb, adapter_->isLegGrounded(limb));
    state_->setIgnoreContact(limb, !adapter_->isLegGrounded(limb));
  }

  state_->setRobotExecutionStatus(true);

  return true;
}

bool Executor::updateStateWithMeasurements()
{
  // Update states for new step.
//  if (!queue_.previousStepExists()) {
    // Update all states.

  for (const auto& limb : adapter_->getLimbs()) {
    const auto& controlSetup = state_->getControlSetup(limb);
    if (!controlSetup.at(ControlLevel::Position)) {
      state_->setJointPositions(limb, adapter_->getJointPositions(limb));
    }
    if (!controlSetup.at(ControlLevel::Velocity)) {
      state_->setJointVelocities(limb, adapter_->getJointVelocities(limb));
    }
    if (!controlSetup.at(ControlLevel::Acceleration)) {
//      state_->setJointAccelerations(limb, adapter_->getJointAccelerations(limb));
    }
    if (!controlSetup.at(ControlLevel::Effort)) {
      state_->setJointEfforts(limb, adapter_->getJointEfforts(limb));
    }
  }

  const auto& controlSetup = state_->getControlSetup(BranchEnum::BASE);
  if (!controlSetup.at(ControlLevel::Position)) {
    state_->setPositionWorldToBaseInWorldFrame(adapter_->getPositionWorldToBaseInWorldFrame());
    state_->setOrientationWorldToBase(adapter_->getOrientationWorldToBase());
  }

  state_->setAllJointVelocities(adapter_->getAllJointVelocities());
  // TODO Copy also acceleraitons and torques.
//    state.setLinearVelocityBaseInWorldFrame(torso_->getMeasuredState().getLinearVelocityBaseInBaseFrame());
//    state.setAngularVelocityBaseInBaseFrame(torso_->getMeasuredState().getAngularVelocityBaseInBaseFrame());
  return true;

}

bool Executor::writeIgnoreContact()
{
  if (!queue_.active()) return true;
  const Step& step = queue_.getCurrentStep();
  for (const auto& limb : adapter_->getLimbs()) {
    if (step.hasLegMotion(limb)) {
      bool ignoreContact = step.getLegMotion(limb).isIgnoreContact();
      state_->setIgnoreContact(limb, ignoreContact);
    }
  }
  return true;
}

bool Executor::writeIgnoreForPoseAdaptation()
{
  if (!queue_.active()) return true;
  const Step& step = queue_.getCurrentStep();
  for (const auto& limb : adapter_->getLimbs()) {
    if (step.hasLegMotion(limb)) {
      bool ignoreForPoseAdaptation = step.getLegMotion(limb).isIgnoreForPoseAdaptation();
      state_->setIgnoreForPoseAdaptation(limb, ignoreForPoseAdaptation);
    }
  }
  return true;
}

bool Executor::writeSupportLegs()
{
  if (!queue_.active()) {
    for (const auto& limb : adapter_->getLimbs()) {
      state_->setSupportLeg(limb, !state_->isIgnoreContact(limb));
    }
    return true;
  }

  const Step& step = queue_.getCurrentStep();
  for (const auto& limb : adapter_->getLimbs()) {
    if (step.hasLegMotion(limb) || state_->isIgnoreContact(limb)) {
      state_->setSupportLeg(limb, false);
    } else {
      state_->setSupportLeg(limb, true);
    }
  }
  return true;
}

bool Executor::writeSurfaceNormals()
{
  if (!queue_.active()) return true;
  const Step& step = queue_.getCurrentStep();
  for (const auto& limb : adapter_->getLimbs()) {
    if (step.hasLegMotion(limb)) {
      if (step.getLegMotion(limb).hasSurfaceNormal()) {
        state_->setSurfaceNormal(limb, step.getLegMotion(limb).getSurfaceNormal());
      }
    }
  }
  return true;
}

bool Executor::writeLegMotion()
{
  for (const auto& limb : adapter_->getLimbs()) {
    if (state_->isSupportLeg(limb)) state_->setEmptyControlSetup(limb);
  }
  if (!queue_.active()) return true;

  const auto& step = queue_.getCurrentStep();
  if (!step.hasLegMotion()) return true;

  double time = queue_.getCurrentStep().getTime();
  for (const auto& limb : adapter_->getLimbs()) {
    if (!step.hasLegMotion(limb)) continue;
    auto const& legMotion = step.getLegMotion(limb);
    ControlSetup controlSetup = legMotion.getControlSetup();
    state_->setControlSetup(limb, controlSetup);

    switch (legMotion.getTrajectoryType()) {

      case LegMotionBase::TrajectoryType::EndEffector:
      {
        const auto& endEffectorMotion = dynamic_cast<const EndEffectorMotionBase&>(legMotion);
        if (controlSetup[ControlLevel::Position]) {
          // TODO Add frame handling.
          Position positionInWorldFrame(endEffectorMotion.evaluatePosition(time));
          Position positionInBaseFrame(adapter_->getOrientationWorldToBase().rotate(positionInWorldFrame - adapter_->getPositionWorldToBaseInWorldFrame()));
          JointPositions jointPositions;
          adapter_->getLimbJointPositionsFromPositionBaseToFootInBaseFrame(positionInBaseFrame, limb, jointPositions);
          state_->setJointPositions(limb, jointPositions);
        }
        break;
      }

      case LegMotionBase::TrajectoryType::Joints:
      {
        const auto& jointMotion = dynamic_cast<const JointMotionBase&>(legMotion);
        if (controlSetup[ControlLevel::Position]) state_->setJointPositions(limb, jointMotion.evaluatePosition(time));
//        if (controlSetup[ControlLevel::Velocity]) state_->setJointVelocities(limb, jointMotion.evaluateVelocity(time));
//        if (controlSetup[ControlLevel::Acceleration]) state_->setJointAcceleration(limb, jointMotion.evaluateAcceleration(time));
        if (controlSetup[ControlLevel::Effort]) state_->setJointEfforts(limb, jointMotion.evaluateEffort(time));
        break;
      }

      default:
        throw std::runtime_error("Executor::writeLegMotion() could not write leg motion of this type.");
        break;
    }
  }
  return true;
}

bool Executor::writeTorsoMotion()
{
  if (state_->getNumberOfSupportLegs() == 0) state_->setEmptyControlSetup(BranchEnum::BASE);
  if (!queue_.active()) return true;

  if (!queue_.getCurrentStep().hasBaseMotion()) return true;
  double time = queue_.getCurrentStep().getTime();
  // TODO Add frame handling.
  const auto& baseMotion = queue_.getCurrentStep().getBaseMotion();
  ControlSetup controlSetup = baseMotion.getControlSetup();
  state_->setControlSetup(BranchEnum::BASE, controlSetup);
  if (controlSetup[ControlLevel::Position]) {
    Pose pose = baseMotion.evaluatePose(time);
    state_->setPositionWorldToBaseInWorldFrame(pose.getPosition());
    state_->setOrientationWorldToBase(pose.getRotation());
  }
  if (controlSetup[ControlLevel::Velocity]) {
    Twist twist = baseMotion.evaluateTwist(time);
    state_->setLinearVelocityBaseInWorldFrame(twist.getTranslationalVelocity());
    state_->setAngularVelocityBaseInBaseFrame(twist.getRotationalVelocity());
  }
  // TODO Set more states.
  return true;
}

} /* namespace free_gait */
<commit_msg>Changes to work with Dario's branch madness.<commit_after>/*
 * Executor.cpp
 *
 *  Created on: Oct 20, 2015
 *      Author: Péter Fankhauser
 *   Institute: ETH Zurich, Autonomous Systems Lab
 */

#include "free_gait_core/executor/Executor.hpp"

#include <robotUtils/timers/ChronoTimer.hpp>

namespace free_gait {

Executor::Executor(std::shared_ptr<StepCompleter> completer,
                   std::shared_ptr<AdapterBase> adapter,
                   std::shared_ptr<State> state)
    : completer_(completer),
      adapter_(adapter),
      state_(state),
      isInitialized_(false)
{
}

Executor::~Executor()
{
}

bool Executor::initialize()
{
  Lock lock(mutex_);
  state_->initialize(adapter_->getLimbs(), adapter_->getBranches());
  reset();
  return isInitialized_ = true;
}

bool Executor::isInitialized() const
{
  return isInitialized_;
}

Executor::Mutex& Executor::getMutex()
{
  return mutex_;
}

bool Executor::advance(double dt)
{
  Lock lock(mutex_);

  if (!isInitialized_) return false;
  updateStateWithMeasurements();

  if (checkRobotStatus()) {
    if (!state_->getRobotExecutionStatus()) std::cout << "Continuing with free gait execution." << std::endl;
    state_->setRobotExecutionStatus(true);
  } else {
    if (state_->getRobotExecutionStatus()) std::cout << "Robot status is not OK, not continuing with free gait execution." << std::endl;
    state_->setRobotExecutionStatus(false);
    return true;
  }

  bool hasSwitchedStep;
  if (!queue_.advance(dt, hasSwitchedStep)) return false;

  while (hasSwitchedStep) {

    if (!queue_.getCurrentStep().requiresMultiThreading()) {
      if (!completeCurrentStep()) return false;
      if (!queue_.advance(dt, hasSwitchedStep)) return false; // Advance again after completion.
    } else {
      std::thread thread(&Executor::completeCurrentStep, this);
      thread.detach();
      hasSwitchedStep = false;
    }
  }

  if (!writeIgnoreContact()) return false;
  if (!writeIgnoreForPoseAdaptation()) return false;
  if (!writeSupportLegs()) return false;
  if (!writeSurfaceNormals()) return false;
  if (!writeLegMotion()) return false;
  if (!writeTorsoMotion()) return false;
  if (!adapter_->updateExtras(queue_, *state_)) return false;
//  std::cout << *state_ << std::endl;
  return true;
}

bool Executor::completeCurrentStep()
{
  robotUtils::HighResolutionClockTimer timer;
  timer.pinTime();

//  if (queue_.getCurrentStep().requiresMultiThreading()) {
//    std::cout << "Taking a break." << std::endl;
//    std::this_thread::sleep_for(std::chrono::seconds(10));
//    std::cout << "Finished break." << std::endl;
//  }

  if (!completer_->complete(*state_, queue_, queue_.getCurrentStep())) {
    std::cerr << "Executor::advance: Could not complete step." << std::endl;
    return false;
  }

  std::cout << "Time to compute step: " << timer.getElapsedTimeMsec() << std::endl;
  std::cout << "Switched step to:" << std::endl;
  std::cout << queue_.getCurrentStep() << std::endl;
  return true;
}

void Executor::reset()
{
  Lock lock(mutex_);
  queue_.clear();
  initializeStateWithRobot();
}

const StepQueue& Executor::getQueue() const
{
  return queue_;
}

StepQueue& Executor::getQueue()
{
  return queue_;
}

const State& Executor::getState() const
{
  return *state_;
}

const AdapterBase& Executor::getAdapter() const
{
  return *adapter_;
}

bool Executor::checkRobotStatus()
{
  for (const auto& limb : adapter_->getLimbs()) {
    if (state_->isSupportLeg(limb) && !adapter_->isLegGrounded(limb)) return false;
  }
  return true;
}

bool Executor::initializeStateWithRobot()
{
  for (const auto& limb : adapter_->getLimbs()) {
    state_->setSupportLeg(limb, adapter_->isLegGrounded(limb));
    state_->setIgnoreContact(limb, !adapter_->isLegGrounded(limb));
    state_->setIgnoreForPoseAdaptation(limb, !adapter_->isLegGrounded(limb));
    state_->removeSurfaceNormal(limb);
  }

  if (state_->getNumberOfSupportLegs() > 0) {
    state_->setControlSetup(BranchEnum::BASE, adapter_->getControlSetup(BranchEnum::BASE));
  } else {
    state_->setEmptyControlSetup(BranchEnum::BASE);
  }

  for (const auto& limb : adapter_->getLimbs()) {
    if (state_->isSupportLeg(limb)) {
      state_->setEmptyControlSetup(limb);
    } else {
      state_->setControlSetup(limb, adapter_->getControlSetup(limb));
    }
  }

  state_->setAllJointPositions(adapter_->getAllJointPositions());
  state_->setAllJointVelocities(adapter_->getAllJointVelocities());
//  state_->setAllJointAccelerations(adapter_->getAllJointAccelerations()); // TODO
  state_->setAllJointEfforts(adapter_->getAllJointEfforts());
  state_->setPositionWorldToBaseInWorldFrame(adapter_->getPositionWorldToBaseInWorldFrame());
  state_->setOrientationWorldToBase(adapter_->getOrientationWorldToBase());

  for (const auto& limb : adapter_->getLimbs()) {
    state_->setSupportLeg(limb, adapter_->isLegGrounded(limb));
    state_->setIgnoreContact(limb, !adapter_->isLegGrounded(limb));
  }

  state_->setRobotExecutionStatus(true);

  return true;
}

bool Executor::updateStateWithMeasurements()
{
  // Update states for new step.
//  if (!queue_.previousStepExists()) {
    // Update all states.

  for (const auto& limb : adapter_->getLimbs()) {
    const auto& controlSetup = state_->getControlSetup(limb);
    if (!controlSetup.at(ControlLevel::Position)) {
      state_->setJointPositions(limb, adapter_->getJointPositions(limb));
    }
    if (!controlSetup.at(ControlLevel::Velocity)) {
      state_->setJointVelocities(limb, adapter_->getJointVelocities(limb));
    }
    if (!controlSetup.at(ControlLevel::Acceleration)) {
//      state_->setJointAccelerations(limb, adapter_->getJointAccelerations(limb));
    }
    if (!controlSetup.at(ControlLevel::Effort)) {
      state_->setJointEfforts(limb, adapter_->getJointEfforts(limb));
    }
  }

  const auto& controlSetup = state_->getControlSetup(BranchEnum::BASE);
  if (!controlSetup.at(ControlLevel::Position)) {
    state_->setPositionWorldToBaseInWorldFrame(adapter_->getPositionWorldToBaseInWorldFrame());
    state_->setOrientationWorldToBase(adapter_->getOrientationWorldToBase());
  }

  state_->setAllJointVelocities(adapter_->getAllJointVelocities());
  // TODO Copy also acceleraitons and torques.
//    state.setLinearVelocityBaseInWorldFrame(torso_->getMeasuredState().getLinearVelocityBaseInBaseFrame());
//    state.setAngularVelocityBaseInBaseFrame(torso_->getMeasuredState().getAngularVelocityBaseInBaseFrame());
  return true;

}

bool Executor::writeIgnoreContact()
{
  if (!queue_.active()) return true;
  const Step& step = queue_.getCurrentStep();
  for (const auto& limb : adapter_->getLimbs()) {
    if (step.hasLegMotion(limb)) {
      bool ignoreContact = step.getLegMotion(limb).isIgnoreContact();
      state_->setIgnoreContact(limb, ignoreContact);
    }
  }
  return true;
}

bool Executor::writeIgnoreForPoseAdaptation()
{
  if (!queue_.active()) return true;
  const Step& step = queue_.getCurrentStep();
  for (const auto& limb : adapter_->getLimbs()) {
    if (step.hasLegMotion(limb)) {
      bool ignoreForPoseAdaptation = step.getLegMotion(limb).isIgnoreForPoseAdaptation();
      state_->setIgnoreForPoseAdaptation(limb, ignoreForPoseAdaptation);
    }
  }
  return true;
}

bool Executor::writeSupportLegs()
{
  if (!queue_.active()) {
    for (const auto& limb : adapter_->getLimbs()) {
      state_->setSupportLeg(limb, !state_->isIgnoreContact(limb));
    }
    return true;
  }

  const Step& step = queue_.getCurrentStep();
  for (const auto& limb : adapter_->getLimbs()) {
    if (step.hasLegMotion(limb) || state_->isIgnoreContact(limb)) {
      state_->setSupportLeg(limb, false);
    } else {
      state_->setSupportLeg(limb, true);
    }
  }
  return true;
}

bool Executor::writeSurfaceNormals()
{
  if (!queue_.active()) return true;
  const Step& step = queue_.getCurrentStep();
  for (const auto& limb : adapter_->getLimbs()) {
    if (step.hasLegMotion(limb)) {
      if (step.getLegMotion(limb).hasSurfaceNormal()) {
        state_->setSurfaceNormal(limb, step.getLegMotion(limb).getSurfaceNormal());
      }
    }
  }
  return true;
}

bool Executor::writeLegMotion()
{
  for (const auto& limb : adapter_->getLimbs()) {
    if (state_->isSupportLeg(limb)) state_->setEmptyControlSetup(limb);
  }
  if (!queue_.active()) return true;

  const auto& step = queue_.getCurrentStep();
  if (!step.hasLegMotion()) return true;

  double time = queue_.getCurrentStep().getTime();
  for (const auto& limb : adapter_->getLimbs()) {
    if (!step.hasLegMotion(limb)) continue;
    auto const& legMotion = step.getLegMotion(limb);
    ControlSetup controlSetup = legMotion.getControlSetup();
    state_->setControlSetup(limb, controlSetup);

    switch (legMotion.getTrajectoryType()) {

      case LegMotionBase::TrajectoryType::EndEffector:
      {
        const auto& endEffectorMotion = dynamic_cast<const EndEffectorMotionBase&>(legMotion);
        if (controlSetup[ControlLevel::Position]) {
          // TODO Add frame handling.
          Position positionInWorldFrame(endEffectorMotion.evaluatePosition(time));
          Position positionInBaseFrame(adapter_->getOrientationWorldToBase().rotate(positionInWorldFrame - adapter_->getPositionWorldToBaseInWorldFrame()));
          JointPositions jointPositions;
          adapter_->getLimbJointPositionsFromPositionBaseToFootInBaseFrame(positionInBaseFrame, limb, jointPositions);
          state_->setJointPositions(limb, jointPositions);
        }
        break;
      }

      case LegMotionBase::TrajectoryType::Joints:
      {
        const auto& jointMotion = dynamic_cast<const JointMotionBase&>(legMotion);
        if (controlSetup[ControlLevel::Position]) state_->setJointPositions(limb, jointMotion.evaluatePosition(time));
//        if (controlSetup[ControlLevel::Velocity]) state_->setJointVelocities(limb, jointMotion.evaluateVelocity(time));
//        if (controlSetup[ControlLevel::Acceleration]) state_->setJointAcceleration(limb, jointMotion.evaluateAcceleration(time));
        if (controlSetup[ControlLevel::Effort]) state_->setJointEfforts(limb, jointMotion.evaluateEffort(time));
        break;
      }

      default:
        throw std::runtime_error("Executor::writeLegMotion() could not write leg motion of this type.");
        break;
    }
  }
  return true;
}

bool Executor::writeTorsoMotion()
{
  if (state_->getNumberOfSupportLegs() == 0) state_->setEmptyControlSetup(BranchEnum::BASE);
  if (!queue_.active()) return true;

  if (!queue_.getCurrentStep().hasBaseMotion()) return true;
  double time = queue_.getCurrentStep().getTime();
  // TODO Add frame handling.
  const auto& baseMotion = queue_.getCurrentStep().getBaseMotion();
  ControlSetup controlSetup = baseMotion.getControlSetup();
  state_->setControlSetup(BranchEnum::BASE, controlSetup);
  if (controlSetup[ControlLevel::Position]) {
    Pose pose = baseMotion.evaluatePose(time);
    state_->setPositionWorldToBaseInWorldFrame(pose.getPosition());
    state_->setOrientationWorldToBase(pose.getRotation());
  }
  if (controlSetup[ControlLevel::Velocity]) {
    Twist twist = baseMotion.evaluateTwist(time);
    state_->setLinearVelocityBaseInWorldFrame(twist.getTranslationalVelocity());
    state_->setAngularVelocityBaseInBaseFrame(twist.getRotationalVelocity());
  }
  // TODO Set more states.
  return true;
}

} /* namespace free_gait */
<|endoftext|>


<commit_before>#ifndef Utils_HPP
#define Utils_HPP
//------------------------------------------------------------------------------
//
// Copyright (c) 2015 Paul Filitchkin, Snapwire
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in
//      the documentation and/or other materials provided with the
//      distribution.
//
//    * Neither the name of the organization nor the names of its contributors
//      may be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//------------------------------------------------------------------------------

#include <string>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <iostream>

// OpenSSL
#include <openssl/md5.h>

// OpenCV
#include <opencv2/imgproc.hpp>

// Exiv2
#include <exiv2/exiv2.hpp>

// Local Third party
#include "thirdparty/rapidjson/writer.h"
#include "thirdparty/rapidjson/prettywriter.h"
#include "thirdparty/rapidjson/stringbuffer.h"

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace Utils
{
  static const std::string FILE_SOURCE = "file://";

  static std::string getStringTail(const std::string& string, int start)
  {
    const int end = string.length() - start;

    return string.substr(start, end);
  }

  //----------------------------------------------------------------------------
  // Compute the MD5 hash of a given array
  //----------------------------------------------------------------------------
  static char* computeMd5(const char* str, int length)
  {
    int n;
    MD5_CTX c;
    unsigned char digest[16];
    char* out = (char*)calloc(1, 33);

    MD5_Init(&c);

    while (length > 0)
    {
      if (length > 512)
      {
        MD5_Update(&c, str, 512);
      }
      else
      {
        MD5_Update(&c, str, length);
      }

      length -= 512;
      str += 512;
    }

    MD5_Final(digest, &c);

    for (n = 0; n < 16; ++n)
    {
      snprintf(&(out[n*2]), 16*2, "%02x", (unsigned int)digest[n]);
    }

    return out;
  }

 //----------------------------------------------------------------------------
 //
 // Copies a transparent 4-channel image over a non-transparent 3 channel
 // background image.
 //
 // Original source:
 //  http://jepsonsblog.blogspot.com.br/2012/10/overlay-transparent-image-in-opencv.html
 //
 // background: must be 3-channel BGR.
 // foreground: must be 4-channel RGBA.
 // output: the destination Mat.
 // location: offset starting point.
 //
 //----------------------------------------------------------------------------
  static void overlayImage(const cv::Mat &background,
                           const cv::Mat &foreground,
                           cv::Mat &output,
                           cv::Point2i location,
                           double blend)
  {
    background.copyTo(output);
    double blendConstant = blend / 255.0;

    // start at the row indicated by location, or at row 0 if location.y is negative.
    for (int y = std::max(location.y, 0); y < background.rows; ++y)
    {
      int fY = y - location.y; // because of the translation

      // we are done or we have processed all rows of the foreground image.
      if (fY >= foreground.rows)
        break;

      // start at the column indicated by location, or at column 0 if location.x is negative.
      for (int x = std::max(location.x, 0); x < background.cols; ++x)
      {
        int fX = x - location.x; // because of the translation.

        // we are done with this row if the column is outside of the foreground image.
        if (fX >= foreground.cols)
          break;

        // determine the opacity of the foreground pixel, using its fourth (alpha) channel.
        unsigned char alpha = foreground.data[fY * foreground.step + fX * foreground.channels() + 3];

        // Only apply watermark if alpha is non-zero
        if (alpha)
        {
          double opacity = blendConstant * ((double) alpha);

          // Combine the background and foreground pixel, using the opacity,
          for (int c = 0; c < output.channels(); ++c)
          {
            unsigned char foregroundPx = foreground.data[fY * foreground.step + fX * foreground.channels() + c];
            unsigned char backgroundPx = background.data[y * background.step + x * background.channels() + c];
            output.data[y * output.step + output.channels() * x + c] = backgroundPx * (1.0 - opacity) + foregroundPx * opacity;
          }
        }
      }
    }
  }

  //------------------------------------------------------------------------------
  //------------------------------------------------------------------------------
  static void exifDebug(Exiv2::ExifData& exifData)
  {
    std::cout << "Has exif!" << std::endl;

    // DEBUG
    Exiv2::ExifData::const_iterator end = exifData.end();

    for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i)
    {
      const char* tn = i->typeName();

      std::cout << std::setw(44)
           << std::setfill(' ') << std::left
           << i->key() << " "
           << "0x" << std::setw(4)
           << std::setfill('0') << std::right
           << std::hex << i->tag() << " "
           << std::setw(9) << std::setfill(' ')
           << std::left << (tn ? tn : "Unknown")
           << " " << std::dec
           << std::setw(3) << std::setfill(' ')
           << std::right << i->count() << "  "
           << std::dec << i->value()
           << "\n";
    }
  }

  //------------------------------------------------------------------------------
  //------------------------------------------------------------------------------
  static void xmpDebug(Exiv2::XmpData& xmpData)
  {
    std::cout << "Has XMP!" << std::endl;

    // DEBUG
    Exiv2::XmpData::const_iterator end = xmpData.end();

    // Output XMP properties
    for (Exiv2::XmpData::const_iterator md = xmpData.begin(); md != xmpData.end(); ++md)
    {
        std::cout << std::setfill(' ') << std::left
                  << std::setw(44)
                  << md->key() << " "
                  << std::setw(9) << std::setfill(' ') << std::left
                  << md->typeName() << " "
                  << std::dec << std::setw(3)
                  << std::setfill(' ') << std::right
                  << md->count() << "  "
                  << std::dec << md->value()
                  << std::endl;
    }
  }

  //------------------------------------------------------------------------------
  //------------------------------------------------------------------------------
  static void iptcDebug(Exiv2::IptcData &iptcData)
  {
    std::cout << "Has IPTC!" << std::endl;

    Exiv2::IptcData::iterator end = iptcData.end();

    for (Exiv2::IptcData::iterator md = iptcData.begin(); md != end; ++md)
    {
      std::cout << std::setw(44) << std::setfill(' ') << std::left
                << md->key() << " "
                << "0x" << std::setw(4) << std::setfill('0') << std::right
                << std::hex << md->tag() << " "
                << std::setw(9) << std::setfill(' ') << std::left
                << md->typeName() << " "
                << std::dec << std::setw(3)
                << std::setfill(' ') << std::right
                << md->count() << "  "
                << std::dec << md->value()
                << std::endl;
    }
  }

  //------------------------------------------------------------------------------
  //------------------------------------------------------------------------------
  static void exitWithError(std::string errorMessage)
  {
    rapidjson::StringBuffer s;

    #ifdef JSON_PRETTY_OUTPUT
      rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(s);
    #else
      rapidjson::Writer<rapidjson::StringBuffer> writer(s);
    #endif

    writer.StartObject();

    // Result
    writer.String("result");
    writer.Bool(false);

    // Error message
    writer.String("error_message");
    writer.String(errorMessage);

    // Assume we weren't able to read any operations
    writer.String("total_operations");
    writer.Uint(0);

    writer.String("failed_operations");
    writer.Uint(0);

    writer.EndObject();

    std::cout << s.GetString() << std::endl;

    exit(-1);
  }

  //------------------------------------------------------------------------------
  //------------------------------------------------------------------------------
//  static std::string outputJsonError(std::string errorMessage, unsigned total_operations, unsigned failed_operations)
//  {
//    rapidjson::StringBuffer s;
//
//    #ifdef JSON_PRETTY_OUTPUT
//      rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(s);
//    #else
//      rapidjson::Writer<rapidjson::StringBuffer> writer(s);
//    #endif
//
//    writer.StartObject();
//
//    // Result
//    writer.String("result");
//    writer.Bool(false);
//
//    // Error message
//    writer.String("error_message");
//    writer.String(errorMessage);
//
//    writer.EndObject();
//
//    return s.GetString();
//  }

  //------------------------------------------------------------------------------
  // Returns a character representation of an OpenCV image type
  //------------------------------------------------------------------------------
  static std::string type2str(int type)
  {
    std::string r;

    uchar depth = type & CV_MAT_DEPTH_MASK;
    uchar chans = 1 + (type >> CV_CN_SHIFT);

    switch ( depth ) {
      case CV_8U:  r = "8U"; break;
      case CV_8S:  r = "8S"; break;
      case CV_16U: r = "16U"; break;
      case CV_16S: r = "16S"; break;
      case CV_32S: r = "32S"; break;
      case CV_32F: r = "32F"; break;
      case CV_64F: r = "64F"; break;
      default:     r = "User"; break;
    }

    r += "C";
    r += (chans+'0');

    return r;
  }
}

#endif // Utils_HPP
<commit_msg>Clean up<commit_after>#ifndef Utils_HPP
#define Utils_HPP
//------------------------------------------------------------------------------
//
// Copyright (c) 2015 Paul Filitchkin, Snapwire
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in
//      the documentation and/or other materials provided with the
//      distribution.
//
//    * Neither the name of the organization nor the names of its contributors
//      may be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//------------------------------------------------------------------------------

#include <string>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <iostream>

// OpenSSL
#include <openssl/md5.h>

// OpenCV
#include <opencv2/imgproc.hpp>

// Exiv2
#include <exiv2/exiv2.hpp>

// Local Third party
#include "thirdparty/rapidjson/writer.h"
#include "thirdparty/rapidjson/prettywriter.h"
#include "thirdparty/rapidjson/stringbuffer.h"

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
namespace Utils
{
  static const std::string FILE_SOURCE = "file://";

  static std::string getStringTail(const std::string& string, int start)
  {
    const int end = string.length() - start;

    return string.substr(start, end);
  }

  //----------------------------------------------------------------------------
  // Compute the MD5 hash of a given array
  //----------------------------------------------------------------------------
  static char* computeMd5(const char* str, int length)
  {
    int n;
    MD5_CTX c;
    unsigned char digest[16];
    char* out = (char*)calloc(1, 33);

    MD5_Init(&c);

    while (length > 0)
    {
      if (length > 512)
      {
        MD5_Update(&c, str, 512);
      }
      else
      {
        MD5_Update(&c, str, length);
      }

      length -= 512;
      str += 512;
    }

    MD5_Final(digest, &c);

    for (n = 0; n < 16; ++n)
    {
      snprintf(&(out[n*2]), 16*2, "%02x", (unsigned int)digest[n]);
    }

    return out;
  }

  //------------------------------------------------------------------------------
  //------------------------------------------------------------------------------
  static void exifDebug(Exiv2::ExifData& exifData)
  {
    std::cout << "Has exif!" << std::endl;

    // DEBUG
    Exiv2::ExifData::const_iterator end = exifData.end();

    for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i)
    {
      const char* tn = i->typeName();

      std::cout << std::setw(44)
           << std::setfill(' ') << std::left
           << i->key() << " "
           << "0x" << std::setw(4)
           << std::setfill('0') << std::right
           << std::hex << i->tag() << " "
           << std::setw(9) << std::setfill(' ')
           << std::left << (tn ? tn : "Unknown")
           << " " << std::dec
           << std::setw(3) << std::setfill(' ')
           << std::right << i->count() << "  "
           << std::dec << i->value()
           << "\n";
    }
  }

  //------------------------------------------------------------------------------
  //------------------------------------------------------------------------------
  static void xmpDebug(Exiv2::XmpData& xmpData)
  {
    std::cout << "Has XMP!" << std::endl;

    // DEBUG
    Exiv2::XmpData::const_iterator end = xmpData.end();

    // Output XMP properties
    for (Exiv2::XmpData::const_iterator md = xmpData.begin(); md != xmpData.end(); ++md)
    {
        std::cout << std::setfill(' ') << std::left
                  << std::setw(44)
                  << md->key() << " "
                  << std::setw(9) << std::setfill(' ') << std::left
                  << md->typeName() << " "
                  << std::dec << std::setw(3)
                  << std::setfill(' ') << std::right
                  << md->count() << "  "
                  << std::dec << md->value()
                  << std::endl;
    }
  }

  //------------------------------------------------------------------------------
  //------------------------------------------------------------------------------
  static void iptcDebug(Exiv2::IptcData &iptcData)
  {
    std::cout << "Has IPTC!" << std::endl;

    Exiv2::IptcData::iterator end = iptcData.end();

    for (Exiv2::IptcData::iterator md = iptcData.begin(); md != end; ++md)
    {
      std::cout << std::setw(44) << std::setfill(' ') << std::left
                << md->key() << " "
                << "0x" << std::setw(4) << std::setfill('0') << std::right
                << std::hex << md->tag() << " "
                << std::setw(9) << std::setfill(' ') << std::left
                << md->typeName() << " "
                << std::dec << std::setw(3)
                << std::setfill(' ') << std::right
                << md->count() << "  "
                << std::dec << md->value()
                << std::endl;
    }
  }

  //------------------------------------------------------------------------------
  //------------------------------------------------------------------------------
  static void exitWithError(std::string errorMessage)
  {
    rapidjson::StringBuffer s;

    #ifdef JSON_PRETTY_OUTPUT
      rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(s);
    #else
      rapidjson::Writer<rapidjson::StringBuffer> writer(s);
    #endif

    writer.StartObject();

    // Result
    writer.String("result");
    writer.Bool(false);

    // Error message
    writer.String("error_message");
    writer.String(errorMessage);

    // Assume we weren't able to read any operations
    writer.String("total_operations");
    writer.Uint(0);

    writer.String("failed_operations");
    writer.Uint(0);

    writer.EndObject();

    std::cout << s.GetString() << std::endl;

    exit(-1);
  }

  //------------------------------------------------------------------------------
  // Returns a character representation of an OpenCV image type
  //------------------------------------------------------------------------------
  static std::string type2str(int type)
  {
    std::string r;

    uchar depth = type & CV_MAT_DEPTH_MASK;
    uchar chans = 1 + (type >> CV_CN_SHIFT);

    switch ( depth ) {
      case CV_8U:  r = "8U"; break;
      case CV_8S:  r = "8S"; break;
      case CV_16U: r = "16U"; break;
      case CV_16S: r = "16S"; break;
      case CV_32S: r = "32S"; break;
      case CV_32F: r = "32F"; break;
      case CV_64F: r = "64F"; break;
      default:     r = "User"; break;
    }

    r += "C";
    r += (chans+'0');

    return r;
  }
}

#endif // Utils_HPP
<|endoftext|>


<commit_before>// Copyright 2015 RethinkDB, all rights reserved.
#ifndef PPRINT_PPRINT_HPP_
#define PPRINT_PPRINT_HPP_

#include <string>
#include <vector>

#include "containers/counted.hpp"

namespace pprint {

class document_visitor_t;
// Pretty printer document.  Has to be `slow_atomic_countable_t`
// because of reuse of things like `br` and `dot`.
class document_t : public slow_atomic_countable_t<document_t> {
public:
    virtual ~document_t() {}
    virtual unsigned int width() const = 0;
    virtual void visit(const document_visitor_t &v) const = 0;
    virtual std::string str() const = 0;
};

// textual element
counted_t<const document_t> make_text(std::string text);

// primitive for conditional linebreaks.
//
// `small` is what will be printed if there is no linebreak.  If there
// is a linebreak, `tail` will be printed on the previous line (think
// Python's need to backslash escape newlines) and `cont` will be
// printed at the start of the new line.
//
// You probably shouldn't use this; use `br` or `dot` when they work.
counted_t<const document_t> make_cond(const std::string small, const std::string cont,
                       const std::string tail);

// document composition
counted_t<const document_t> make_concat(std::vector<counted_t<const document_t> > args);
counted_t<const document_t>
make_concat(std::initializer_list<counted_t<const document_t> > args);

template <typename... Ts>
inline counted_t<const document_t> make_concat(Ts... docs) {
    return make_concat({docs...});
}

// document enclosure where all linebreaks are interpreted consistently.
counted_t<const document_t> make_group(counted_t<const document_t> doc);

// document enclosure where all linebreaks are indented to the start of the nest.
//
// implicitly wraps `doc` in a group.
counted_t<const document_t> make_nest(counted_t<const document_t> doc);

extern const counted_t<const document_t> empty;
extern const counted_t<const document_t> br;
extern const counted_t<const document_t> dot;

// documents separated by commas and then a `br`.
//
// think `1, 2, 3`
counted_t<const document_t>
comma_separated(std::initializer_list<counted_t<const document_t> > init);

template <typename... Ts>
inline counted_t<const document_t> comma_separated(Ts... docs) {
    return comma_separated({docs...});
}

// argument list; comma separated arguments wrapped in parens with a nest.
//
// think `(1, 2, 3)`
counted_t<const document_t>
arglist(std::initializer_list<counted_t<const document_t> >);

template <typename... Ts>
inline counted_t<const document_t> arglist(Ts... docs) {
    return arglist({docs...});
}

// documents separated by `dot`.
//
// think `r.foo().bar().baz()`
counted_t<const document_t>
dotted_list(std::initializer_list<counted_t<const document_t> >);

template <typename... Ts>
inline counted_t<const document_t> dotted_list(Ts... docs) {
    return dotted_list({docs...});
}

// function call document, where `name` is the call and `init` are the args.
//
// think `foo(1, 2, 3)`
counted_t<const document_t>
funcall(const std::string &, std::initializer_list<counted_t<const document_t> >);

template <typename... Ts>
inline counted_t<const document_t> funcall(const std::string &name, Ts... docs) {
    return funcall(name, {docs...});
}

// helper for r.foo.bar.baz expressions.
counted_t<const document_t> r_dot(std::initializer_list<counted_t<const document_t> >);

template <typename... Ts>
inline counted_t<const document_t> r_dot(Ts... docs) {
    return r_dot({docs...});
}

// render document at the given width.
std::string pretty_print(unsigned int width, counted_t<const document_t> doc);

} // namespace pprint

#endif  // PPRINT_PPRINT_HPP_
<commit_msg>Insert `std::forward` juju<commit_after>// Copyright 2015 RethinkDB, all rights reserved.
#ifndef PPRINT_PPRINT_HPP_
#define PPRINT_PPRINT_HPP_

#include <string>
#include <vector>
#include <utility>

#include "containers/counted.hpp"

namespace pprint {

class document_visitor_t;
// Pretty printer document.  Has to be `slow_atomic_countable_t`
// because of reuse of things like `br` and `dot`.
class document_t : public slow_atomic_countable_t<document_t> {
public:
    virtual ~document_t() {}
    virtual unsigned int width() const = 0;
    virtual void visit(const document_visitor_t &v) const = 0;
    virtual std::string str() const = 0;
};

// textual element
counted_t<const document_t> make_text(std::string text);

// primitive for conditional linebreaks.
//
// `small` is what will be printed if there is no linebreak.  If there
// is a linebreak, `tail` will be printed on the previous line (think
// Python's need to backslash escape newlines) and `cont` will be
// printed at the start of the new line.
//
// You probably shouldn't use this; use `br` or `dot` when they work.
counted_t<const document_t> make_cond(const std::string small, const std::string cont,
                       const std::string tail);

// document composition
counted_t<const document_t> make_concat(std::vector<counted_t<const document_t> > args);
counted_t<const document_t>
make_concat(std::initializer_list<counted_t<const document_t> > args);

template <typename... Ts>
inline counted_t<const document_t> make_concat(Ts &&... docs) {
    return make_concat({std::forward<Ts>(docs)...});
}

// document enclosure where all linebreaks are interpreted consistently.
counted_t<const document_t> make_group(counted_t<const document_t> doc);

// document enclosure where all linebreaks are indented to the start of the nest.
//
// implicitly wraps `doc` in a group.
counted_t<const document_t> make_nest(counted_t<const document_t> doc);

extern const counted_t<const document_t> empty;
extern const counted_t<const document_t> br;
extern const counted_t<const document_t> dot;

// documents separated by commas and then a `br`.
//
// think `1, 2, 3`
counted_t<const document_t>
comma_separated(std::initializer_list<counted_t<const document_t> > init);

template <typename... Ts>
inline counted_t<const document_t> comma_separated(Ts &&... docs) {
    return comma_separated({std::forward<Ts>(docs)...});
}

// argument list; comma separated arguments wrapped in parens with a nest.
//
// think `(1, 2, 3)`
counted_t<const document_t>
arglist(std::initializer_list<counted_t<const document_t> >);

template <typename... Ts>
inline counted_t<const document_t> arglist(Ts &&... docs) {
    return arglist({std::forward<Ts>(docs)...});
}

// documents separated by `dot`.
//
// think `r.foo().bar().baz()`
counted_t<const document_t>
dotted_list(std::initializer_list<counted_t<const document_t> >);

template <typename... Ts>
inline counted_t<const document_t> dotted_list(Ts &&... docs) {
    return dotted_list({std::forward<Ts>(docs)...});
}

// function call document, where `name` is the call and `init` are the args.
//
// think `foo(1, 2, 3)`
counted_t<const document_t>
funcall(const std::string &, std::initializer_list<counted_t<const document_t> >);

template <typename... Ts>
inline counted_t<const document_t> funcall(const std::string &name, Ts &&... docs) {
    return funcall(name, {std::forward<Ts>(docs)...});
}

// helper for r.foo.bar.baz expressions.
counted_t<const document_t> r_dot(std::initializer_list<counted_t<const document_t> >);

template <typename... Ts>
inline counted_t<const document_t> r_dot(Ts &&... docs) {
    return r_dot({std::forward<Ts>(docs)...});
}

// render document at the given width.
std::string pretty_print(unsigned int width, counted_t<const document_t> doc);

} // namespace pprint

#endif  // PPRINT_PPRINT_HPP_
<|endoftext|>


<commit_before>#include "ShadingWithLightCulling.h"
#include "EngineShaderFactory.hpp"
#include "Director.h"
#include "ResourceManager.h"

using namespace Device;
using namespace Core;
using namespace Rendering;
using namespace Resource;
using namespace Rendering::Light;
using namespace Rendering::Buffer;
using namespace Rendering::Shader;
using namespace Rendering::Texture;
using namespace GPGPU::DirectCompute;
using namespace Rendering::TBDR;

ShadingWithLightCulling::ShadingWithLightCulling() : _offScreen(nullptr)
{

}

ShadingWithLightCulling::~ShadingWithLightCulling()
{
	Destory();
}

void ShadingWithLightCulling::Initialize(
	const Texture::DepthBuffer* opaqueDepthBuffer,
	const GBuffers& geometryBuffers,
	const Math::Size<uint>& backBufferSize,
	bool useDebugMode)
{
	const Core::Scene* scene				= Director::SharedInstance()->GetCurrentScene();
	Manager::LightManager* lightManager		= scene->GetLightManager();
	Shadow::ShadowRenderer* shadowMgr		= scene->GetShadowManager();

	std::string filePath = "";
	{
		Factory::EngineFactory pathFind(nullptr);
		pathFind.FetchShaderFullPath(filePath, "TBDR");

		ASSERT_COND_MSG(filePath.empty() == false, "Error, File path is empty");
	}

	std::vector<ShaderMacro> macros;
	{
		if(useDebugMode)
			macros.push_back(ShaderMacro("DEBUG_MODE", ""));

		if(shadowMgr->GetNeverUseVSM())
			macros.push_back(ShaderMacro("NEVER_USE_VSM", ""));
	}

	LightCulling::Initialize(filePath, "TileBasedDeferredShadingCS", opaqueDepthBuffer, nullptr, &macros);

	// Input Shader Resource Buffers
	AddInputBufferToList(uint(TextureBindIndex::DirectionalLightCenterWithDirZ),		lightManager->GetDirectionalLightTransformSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::DirectionalLightColor),					lightManager->GetDirectionalLightColorSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::DirectionalLightParam),					lightManager->GetDirectionalLightParamSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::DirectionalLightShadowParam),			shadowMgr->GetDirectionalLightShadowParamSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::DirectionalLightShadowIndex),			lightManager->GetDirectionalLightShadowIndexSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::DirectionalLightShadowViewProjMatrix),	shadowMgr->GetDirectionalLightShadowViewProjSRBuffer());

	// Point Light transform LightCulling::Initialize ϰ ִ.
	AddInputBufferToList(uint(TextureBindIndex::PointLightColor),						lightManager->GetPointLightColorSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::PointLightShadowParam),					shadowMgr->GetPointLightShadowParamSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::PointLightShadowIndex),					lightManager->GetPointLightShadowIndexSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::PointLightShadowViewProjMatrix),		shadowMgr->GetPointLightShadowViewProjSRBuffer());

	// Spot Light transform Param LightCulling::Initialize ϰ ִ.
	AddInputBufferToList(uint(TextureBindIndex::SpotLightColor),						lightManager->GetSpotLightColorSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::SpotLightShadowParam),					shadowMgr->GetSpotLightShadowParamSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::SpotLightShadowIndex),					lightManager->GetSpotLightShadowIndexSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::SpotLightShadowViewProjMatrix),			shadowMgr->GetSpotLightShadowViewProjSRBuffer());

	// Input Texture
	{
		ResourceManager* resMgr = ResourceManager::SharedInstance();

		AddTextureToInputTextureList(uint(TextureBindIndex::GBuffer_Albedo_Occlusion),			geometryBuffers.albedo_occlusion);
		AddTextureToInputTextureList(uint(TextureBindIndex::GBuffer_MotionXY_Height_Metallic),	geometryBuffers.motionXY_height_metallic);
		AddTextureToInputTextureList(uint(TextureBindIndex::GBuffer_Normal_Roughness),			geometryBuffers.normal_roughness);
		AddTextureToInputTextureList(uint(TextureBindIndex::GBuffer_Emission_Specularity),					geometryBuffers.emission);

		// ShadowMap Atlas
		{
			AddTextureToInputTextureList(uint(TextureBindIndex::PointLightShadowMapAtlas),			shadowMgr->GetPointLightShadowMapAtlas());
			AddTextureToInputTextureList(uint(TextureBindIndex::SpotLightShadowMapAtlas),			shadowMgr->GetSpotLightShadowMapAtlas());
			AddTextureToInputTextureList(uint(TextureBindIndex::DirectionalLightShadowMapAtlas),	shadowMgr->GetDirectionalLightShadowMapAtlas());

			if(shadowMgr->GetNeverUseVSM() == false)
			{
				AddTextureToInputTextureList(uint(TextureBindIndex::PointLightMomentShadowMapAtlas),		shadowMgr->GetPointLightMomentShadowMapAtlas());
				AddTextureToInputTextureList(uint(TextureBindIndex::SpotLightMomentShadowMapAtlas),			shadowMgr->GetSpotLightMomentShadowMapAtlas());
				AddTextureToInputTextureList(uint(TextureBindIndex::DirectionalLightMomentShadowMapAtlas),	shadowMgr->GetDirectionalLightMomentShadowMapAtlas());
			}
		}
	}

	// Offscreen
	{
		Math::Size<uint> bufferSize = backBufferSize;
		{
			const DXGI_SAMPLE_DESC& msaaDesc = Director::SharedInstance()->GetDirectX()->GetMSAADesc();
			if(msaaDesc.Count > 1)
			{
				bufferSize.w *= 2;
				bufferSize.h *= 2;
			}
		}

		_offScreen = new RenderTexture;
		_offScreen->Initialize(bufferSize, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, D3D11_BIND_UNORDERED_ACCESS, 1);

		ShaderForm::InputUnorderedAccessView output;
		{
			output.bindIndex	= (uint)UAVBindIndex::TBDR_OutScreen;
			output.uav			= _offScreen->GetUnorderedAccessView();
		}

		std::vector<ShaderForm::InputUnorderedAccessView> outputs;
		outputs.push_back(output);

		SetOuputBuferToCS(outputs);
	}

	SetInputsToCS();
}

void ShadingWithLightCulling::Destory()
{
	SAFE_DELETE(_offScreen);
	LightCulling::Destroy();
}

void ShadingWithLightCulling::Dispatch(const Device::DirectX* dx,
									   const Buffer::ConstBuffer* tbrConstBuffer,
									   const Buffer::ConstBuffer* shadowGlobalParamConstBuffer)
{
	std::vector<ShaderForm::InputConstBuffer> additionalConstBuffers;
	if(shadowGlobalParamConstBuffer)
	{
		ShaderForm::InputConstBuffer icb;
		icb.buffer		= shadowGlobalParamConstBuffer;
		icb.bindIndex	= (uint)ConstBufferBindIndex::ShadowGlobalParam;

		additionalConstBuffers.push_back(icb);
	}

	LightCulling::Dispatch(dx, tbrConstBuffer, &additionalConstBuffers);
}<commit_msg>코드 정리<commit_after>#include "ShadingWithLightCulling.h"
#include "EngineShaderFactory.hpp"
#include "Director.h"
#include "ResourceManager.h"

using namespace Device;
using namespace Core;
using namespace Rendering;
using namespace Resource;
using namespace Rendering::Light;
using namespace Rendering::Buffer;
using namespace Rendering::Shader;
using namespace Rendering::Texture;
using namespace GPGPU::DirectCompute;
using namespace Rendering::TBDR;

ShadingWithLightCulling::ShadingWithLightCulling() : _offScreen(nullptr)
{

}

ShadingWithLightCulling::~ShadingWithLightCulling()
{
	Destory();
}

void ShadingWithLightCulling::Initialize(
	const Texture::DepthBuffer* opaqueDepthBuffer,
	const GBuffers& geometryBuffers,
	const Math::Size<uint>& backBufferSize,
	bool useDebugMode)
{
	const Core::Scene* scene				= Director::SharedInstance()->GetCurrentScene();
	Manager::LightManager* lightManager		= scene->GetLightManager();
	Shadow::ShadowRenderer* shadowMgr		= scene->GetShadowManager();

	std::string filePath = "";
	{
		Factory::EngineFactory pathFind(nullptr);
		pathFind.FetchShaderFullPath(filePath, "TBDR");

		ASSERT_COND_MSG(filePath.empty() == false, "Error, File path is empty");
	}

	std::vector<ShaderMacro> macros;
	{
		if(useDebugMode)
			macros.push_back(ShaderMacro("DEBUG_MODE", ""));

		if(shadowMgr->GetNeverUseVSM())
			macros.push_back(ShaderMacro("NEVER_USE_VSM", ""));
	}

	LightCulling::Initialize(filePath, "TileBasedDeferredShadingCS", opaqueDepthBuffer, nullptr, &macros);

	// Input Shader Resource Buffers
	AddInputBufferToList(uint(TextureBindIndex::DirectionalLightCenterWithDirZ),		lightManager->GetDirectionalLightTransformSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::DirectionalLightColor),					lightManager->GetDirectionalLightColorSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::DirectionalLightParam),					lightManager->GetDirectionalLightParamSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::DirectionalLightShadowParam),			shadowMgr->GetDirectionalLightShadowParamSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::DirectionalLightShadowIndex),			lightManager->GetDirectionalLightShadowIndexSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::DirectionalLightShadowViewProjMatrix),	shadowMgr->GetDirectionalLightShadowViewProjSRBuffer());

	// Point Light transform LightCulling::Initialize ϰ ִ.
	AddInputBufferToList(uint(TextureBindIndex::PointLightColor),						lightManager->GetPointLightColorSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::PointLightShadowParam),					shadowMgr->GetPointLightShadowParamSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::PointLightShadowIndex),					lightManager->GetPointLightShadowIndexSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::PointLightShadowViewProjMatrix),		shadowMgr->GetPointLightShadowViewProjSRBuffer());

	// Spot Light transform Param LightCulling::Initialize ϰ ִ.
	AddInputBufferToList(uint(TextureBindIndex::SpotLightColor),						lightManager->GetSpotLightColorSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::SpotLightShadowParam),					shadowMgr->GetSpotLightShadowParamSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::SpotLightShadowIndex),					lightManager->GetSpotLightShadowIndexSRBuffer());
	AddInputBufferToList(uint(TextureBindIndex::SpotLightShadowViewProjMatrix),			shadowMgr->GetSpotLightShadowViewProjSRBuffer());

	// Input Texture
	{
		ResourceManager* resMgr = ResourceManager::SharedInstance();

		AddTextureToInputTextureList(uint(TextureBindIndex::GBuffer_Albedo_Occlusion),			geometryBuffers.albedo_occlusion);
		AddTextureToInputTextureList(uint(TextureBindIndex::GBuffer_MotionXY_Height_Metallic),	geometryBuffers.motionXY_height_metallic);
		AddTextureToInputTextureList(uint(TextureBindIndex::GBuffer_Normal_Roughness),			geometryBuffers.normal_roughness);
		AddTextureToInputTextureList(uint(TextureBindIndex::GBuffer_Emission_Specularity),		geometryBuffers.emission);

		// ShadowMap Atlas
		{
			AddTextureToInputTextureList(uint(TextureBindIndex::PointLightShadowMapAtlas),			shadowMgr->GetPointLightShadowMapAtlas());
			AddTextureToInputTextureList(uint(TextureBindIndex::SpotLightShadowMapAtlas),			shadowMgr->GetSpotLightShadowMapAtlas());
			AddTextureToInputTextureList(uint(TextureBindIndex::DirectionalLightShadowMapAtlas),	shadowMgr->GetDirectionalLightShadowMapAtlas());

			if(shadowMgr->GetNeverUseVSM() == false)
			{
				AddTextureToInputTextureList(uint(TextureBindIndex::PointLightMomentShadowMapAtlas),		shadowMgr->GetPointLightMomentShadowMapAtlas());
				AddTextureToInputTextureList(uint(TextureBindIndex::SpotLightMomentShadowMapAtlas),			shadowMgr->GetSpotLightMomentShadowMapAtlas());
				AddTextureToInputTextureList(uint(TextureBindIndex::DirectionalLightMomentShadowMapAtlas),	shadowMgr->GetDirectionalLightMomentShadowMapAtlas());
			}
		}
	}

	// Offscreen
	{
		Math::Size<uint> bufferSize = backBufferSize;
		{
			const DXGI_SAMPLE_DESC& msaaDesc = Director::SharedInstance()->GetDirectX()->GetMSAADesc();
			if(msaaDesc.Count > 1)
			{
				bufferSize.w *= 2;
				bufferSize.h *= 2;
			}
		}

		_offScreen = new RenderTexture;
		_offScreen->Initialize(bufferSize, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, D3D11_BIND_UNORDERED_ACCESS, 1);

		ShaderForm::InputUnorderedAccessView output;
		{
			output.bindIndex	= (uint)UAVBindIndex::TBDR_OutScreen;
			output.uav			= _offScreen->GetUnorderedAccessView();
		}

		std::vector<ShaderForm::InputUnorderedAccessView> outputs;
		outputs.push_back(output);

		SetOuputBuferToCS(outputs);
	}

	SetInputsToCS();
}

void ShadingWithLightCulling::Destory()
{
	SAFE_DELETE(_offScreen);
	LightCulling::Destroy();
}

void ShadingWithLightCulling::Dispatch(const Device::DirectX* dx,
									   const Buffer::ConstBuffer* tbrConstBuffer,
									   const Buffer::ConstBuffer* shadowGlobalParamConstBuffer)
{
	std::vector<ShaderForm::InputConstBuffer> additionalConstBuffers;
	if(shadowGlobalParamConstBuffer)
	{
		ShaderForm::InputConstBuffer icb;
		icb.buffer		= shadowGlobalParamConstBuffer;
		icb.bindIndex	= (uint)ConstBufferBindIndex::ShadowGlobalParam;

		additionalConstBuffers.push_back(icb);
	}

	LightCulling::Dispatch(dx, tbrConstBuffer, &additionalConstBuffers);
}<|endoftext|>