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

Library:   TubeTK

Copyright 2010 Kitware Inc. 28 Corporate Drive,
Clifton Park, NY, 12065, USA.

All rights reserved.

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

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.

=========================================================================*/

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

#include "itkOrientedImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

// The following three should be used in every CLI application
#include "tubeMessage.h"
#include "tubeCLIFilterWatcher.h"
#include "tubeCLIProgressReporter.h"
#include "itkTimeProbesCollectorBase.h"

// Application-specific includes
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkAmoebaOptimizer.h"
#include "itkImageRegionIterator.h"
#include "itkRecursiveGaussianImageFilter.h"
#include "itkIdentityTransform.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkMeanSquaresImageToImageMetric.h"
#include "itkNormalizeImageFilter.h"

// Must do a forward declaraction of DoIt before including
// tubeCLIHelperFunctions
template< class pixelT, unsigned int dimensionT >
int DoIt( int argc, char * argv[] );

// Must include CLP before including tubeCLIHleperFunctions
#include "DeblendImagesUsingPriorCLP.h"

// Includes tube::ParseArgsAndCallDoIt function
#include "tubeCLIHelperFunctions.h"

namespace itk {

template< class pixelT, unsigned int dimensionT >
class BlendCostFunction
: public SingleValuedCostFunction
  {
  public:

    typedef BlendCostFunction           Self;
    typedef SingleValuedCostFunction    Superclass;
    typedef SmartPointer< Self >        Pointer;
    typedef SmartPointer< const Self >  ConstPointer;

    itkTypeMacro( BlendCostFunction, SingleValuedCostFunction );

    itkNewMacro( Self );

    typedef Superclass::MeasureType     MeasureType;
    typedef Superclass::ParametersType  ParametersType;
    typedef Superclass::DerivativeType  DerivativeType;

    typedef itk::OrientedImage<pixelT, dimensionT>  ImageType;

    unsigned int GetNumberOfParameters( void ) const
      {
      return 4;
      }

    void SetImageTop( typename ImageType::Pointer _top )
      {
      m_ImageTop = _top;
      }
    void SetImageMiddle( typename ImageType::Pointer _middle )
      {
      m_ImageMiddle = _middle;
      }
    void SetImageBottom( typename ImageType::Pointer _bottom )
      {
      m_ImageBottom = _bottom;
      }
    void SetMaskMiddle( typename ImageType::Pointer _maskMiddle )
      {
      m_MaskMiddle = _maskMiddle;
      }
    void SetImageOutput( typename ImageType::Pointer _output )
      {
      m_ImageOutput = _output;
      }

    void GetDerivative( const ParametersType & params,
                        DerivativeType & deriv ) const
      {
      ParametersType unusedP = params;
      DerivativeType unusedD = deriv;
      return;
      }

    MeasureType GetValue( const ParametersType & params ) const
      {
      static unsigned int calls = 0;

      typedef itk::ImageRegionIterator< ImageType >
        ImageIteratorType;
      typedef itk::RecursiveGaussianImageFilter< ImageType, ImageType >
        FilterType;

      if( params[3] < 0.2 )
        {
        return 10000;
        }

      typename FilterType::Pointer filterTop = FilterType::New();
      filterTop->SetInput( m_ImageTop );
      filterTop->SetSigma( params[3] );
      filterTop->Update();
      typename ImageType::Pointer imageTopB = filterTop->GetOutput();

      typename FilterType::Pointer filterBottom = FilterType::New();
      filterBottom->SetInput( m_ImageBottom );
      filterBottom->SetSigma( params[3] );
      filterBottom->Update();
      typename ImageType::Pointer imageBottomB = filterBottom->GetOutput();

      ImageIteratorType iterTopB( imageTopB,
                               imageTopB->GetLargestPossibleRegion() );
      ImageIteratorType iterBottomB( imageBottomB,
                               imageBottomB->GetLargestPossibleRegion() );
      ImageIteratorType iterMiddle( m_ImageMiddle,
                               m_ImageMiddle->GetLargestPossibleRegion() );
      ImageIteratorType iterOutput( m_ImageOutput,
                               m_ImageOutput->GetLargestPossibleRegion() );
      while( !iterMiddle.IsAtEnd() )
        {
        float tf = params[0] * iterTopB.Get() +
                   params[1] * iterBottomB.Get() +
                   params[2];

        iterOutput.Set( iterMiddle.Get() - tf );

        ++iterMiddle;
        ++iterTopB;
        ++iterBottomB;
        ++iterOutput;
        }

      typedef itk::IdentityTransform< double, dimensionT >
        TransformType;
      typename TransformType::Pointer transform = TransformType::New();

      typedef itk::LinearInterpolateImageFunction< ImageType, double >
        InterpolatorType;
      typename InterpolatorType::Pointer interpolator =
        InterpolatorType::New();
      interpolator->SetInputImage( m_ImageOutput );

      typename ImageType::SizeType size;
      size = m_ImageMiddle->GetLargestPossibleRegion().GetSize();

      typedef itk::MeanSquaresImageToImageMetric< ImageType, ImageType >
                                                             MetricType;
      typename MetricType::Pointer metric = MetricType::New();

      double samplingRate = 0.5;
      metric->SetFixedImage( m_MaskMiddle );
      metric->SetMovingImage( m_ImageOutput );
      metric->SetFixedImageRegion( m_MaskMiddle->
                                     GetLargestPossibleRegion() );
      metric->SetTransform( transform );
      metric->SetInterpolator( interpolator );
      metric->SetNumberOfSpatialSamples( size[0]*size[1]*samplingRate );
      metric->Initialize();
      metric->MultiThreadingInitialize();

      double result = metric->GetValue( transform->GetParameters() ) ;

      std::cout << ++calls << ": "
                << params[0] << ", "
                << params[1] << ", "
                << params[2] << ", "
                << params[3]
                << " : result =" << result << std::endl;

      return result;
      }

  protected:
    BlendCostFunction() {};
    virtual ~BlendCostFunction() {};

    void PrintSelf( std::ostream & os, Indent indent ) const
      {
      Superclass::PrintSelf( os, indent );
      }

  private:
    BlendCostFunction( const Self & );
    void operator=( const Self & );

    typename ImageType::Pointer         m_ImageTop;
    typename ImageType::Pointer         m_ImageMiddle;
    typename ImageType::Pointer         m_ImageBottom;
    typename ImageType::Pointer         m_MaskMiddle;
    mutable typename ImageType::Pointer m_ImageOutput;

  };

}; //namespace itk

template< class pixelT, unsigned int dimensionT >
int DoIt( int argc, char * argv[] )
{
  PARSE_ARGS;

  // The timeCollector is used to perform basic profiling of the components
  //   of your algorithm.
  itk::TimeProbesCollectorBase timeCollector;

  // CLIProgressReporter is used to communicate progress with Slicer GUI
  tube::CLIProgressReporter    progressReporter( "DeblendImagesUsingPrior",
                                                 CLPProcessInformation );
  progressReporter.Start();

  typedef float                                         PixelType;
  typedef itk::OrientedImage< PixelType,  dimensionT >  ImageType;

  /** Read input images */
  typename ImageType::Pointer imageTop;
  typename ImageType::Pointer imageMiddle;
  typename ImageType::Pointer imageBottom;
  typename ImageType::Pointer maskMiddle;

  timeCollector.Start("Read");
    {
    typedef itk::ImageFileReader< ImageType >   ReaderType;

    typename ReaderType::Pointer readerTop = ReaderType::New();
    typename ReaderType::Pointer readerMiddle = ReaderType::New();
    typename ReaderType::Pointer readerBottom = ReaderType::New();
    typename ReaderType::Pointer readerMask = ReaderType::New();

    //read input image
    readerTop->SetFileName( inputTop.c_str() );
    readerMiddle->SetFileName( inputMiddle.c_str() );
    readerBottom->SetFileName( inputBottom.c_str() );
    readerMask->SetFileName( inputMask.c_str() );

    try
      {
      readerTop->Update();
      }
    catch( itk::ExceptionObject & err )
      {
      tube::ErrorMessage( "Reading top. Exception caught: "
                          + std::string(err.GetDescription()) );
      timeCollector.Report();
      return EXIT_FAILURE;
      }

    try
      {
      readerMiddle->Update();
      }
    catch( itk::ExceptionObject & err )
      {
      tube::ErrorMessage( "Reading middle. Exception caught: "
                          + std::string(err.GetDescription()) );
      timeCollector.Report();
      return EXIT_FAILURE;
      }

    try
      {
      readerBottom->Update();
      }
    catch( itk::ExceptionObject & err )
      {
      tube::ErrorMessage( "Reading bottom. Exception caught: "
                          + std::string(err.GetDescription()) );
      timeCollector.Report();
      return EXIT_FAILURE;
      }

    try
      {
      readerMask->Update();
      }
    catch( itk::ExceptionObject & err )
      {
      tube::ErrorMessage( "Reading mask. Exception caught: "
                          + std::string(err.GetDescription()) );
      timeCollector.Report();
      return EXIT_FAILURE;
      }

    typedef itk::NormalizeImageFilter< ImageType, ImageType > NormFilterType;
    typename NormFilterType::Pointer normTop = NormFilterType::New();
    normTop->SetInput( readerTop->GetOutput() );
    normTop->Update();
    imageTop = normTop->GetOutput();

    typename NormFilterType::Pointer normMiddle = NormFilterType::New();
    normMiddle->SetInput( readerMiddle->GetOutput() );
    normMiddle->Update();
    imageMiddle = normMiddle->GetOutput();

    typename NormFilterType::Pointer normBottom = NormFilterType::New();
    normBottom->SetInput( readerBottom->GetOutput() );
    normBottom->Update();
    imageBottom = normBottom->GetOutput();

    typename NormFilterType::Pointer normMask = NormFilterType::New();
    normMask->SetInput( readerMask->GetOutput() );
    normMask->Update();
    maskMiddle = normMask->GetOutput();
    }
  progressReporter.Report( 0.1 );
  timeCollector.Stop("Read");

  typedef itk::BlendCostFunction< PixelType, dimensionT >
                                                BlendCostFunctionType;
  typedef itk::AmoebaOptimizer                    OptimizerType;;
  typedef itk::ImageRegionIterator< ImageType > ImageIteratorType;

   itk::Array<double> params(4);
  params[0] = alpha;
  params[1] = beta;
  params[2] = gamma;
  params[3] = sigma;

  typename BlendCostFunctionType::Pointer costFunc =
    BlendCostFunctionType::New();
  costFunc->SetImageTop( imageTop );
  costFunc->SetImageMiddle( imageMiddle );
  costFunc->SetImageBottom( imageBottom );
  costFunc->SetMaskMiddle( maskMiddle );

  OptimizerType::Pointer optimizer = OptimizerType::New();
  optimizer->SetMaximumNumberOfIterations( iterations );
  optimizer->SetMaximize( false );

  OptimizerType::ScalesType scales( 4 );
  scales[0] = 1.0 / 0.05;
  scales[1] = 1.0 / 0.05;
  scales[2] = 1.0 / 1;
  scales[3] = 1.0 / 0.2;
  optimizer->SetScales( scales );

  optimizer->SetCostFunction( costFunc );
  optimizer->SetInitialPosition( params );

  //
  // Generate output image
  //
  typename ImageType::Pointer imageOutput = ImageType::New();
  imageOutput->CopyInformation( imageMiddle );
  imageOutput->SetRegions( imageMiddle->GetLargestPossibleRegion() );
  imageOutput->Allocate();
  costFunc->SetImageOutput( imageOutput );

  optimizer->StartOptimization();

  params = optimizer->GetCurrentPosition();
  double result = costFunc->GetValue( params );
  std::cout << "Winning params = " << params
            << " Result = " << result << std::endl;

  typedef itk::ImageFileWriter< ImageType  >   ImageWriterType;
  typename ImageWriterType::Pointer writer = ImageWriterType::New();

  writer->SetFileName( outputMiddle.c_str() );
  writer->SetInput( imageOutput );
  writer->SetUseCompression( true );
  try
    {
    writer->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    tube::ErrorMessage( "Writing volume. Exception caught: "
                        + std::string(err.GetDescription()) );
    timeCollector.Report();
    return EXIT_FAILURE;
    }

  progressReporter.Report( 1.0 );
  progressReporter.End( );

  timeCollector.Report();
  return EXIT_SUCCESS;
}

int main( int argc, char **argv )
{
  PARSE_ARGS;

  return tube::ParseArgsAndCallDoIt( inputMiddle, argc, argv );
}
<commit_msg>STYLE: Fixed some indentation and alignment problems.<commit_after>/*=========================================================================

Library:   TubeTK

Copyright 2010 Kitware Inc. 28 Corporate Drive,
Clifton Park, NY, 12065, USA.

All rights reserved.

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

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.

=========================================================================*/

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

#include "itkOrientedImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"

// The following three should be used in every CLI application
#include "tubeMessage.h"
#include "tubeCLIFilterWatcher.h"
#include "tubeCLIProgressReporter.h"
#include "itkTimeProbesCollectorBase.h"

// Application-specific includes
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkAmoebaOptimizer.h"
#include "itkImageRegionIterator.h"
#include "itkRecursiveGaussianImageFilter.h"
#include "itkIdentityTransform.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkMeanSquaresImageToImageMetric.h"
#include "itkNormalizeImageFilter.h"

// Must do a forward declaraction of DoIt before including
// tubeCLIHelperFunctions
template< class pixelT, unsigned int dimensionT >
int DoIt( int argc, char * argv[] );

// Must include CLP before including tubeCLIHleperFunctions
#include "DeblendImagesUsingPriorCLP.h"

// Includes tube::ParseArgsAndCallDoIt function
#include "tubeCLIHelperFunctions.h"

namespace itk {

template< class pixelT, unsigned int dimensionT >
class BlendCostFunction
: public SingleValuedCostFunction
{
public:

  typedef BlendCostFunction                       Self;
  typedef SingleValuedCostFunction                Superclass;
  typedef SmartPointer< Self >                    Pointer;
  typedef SmartPointer< const Self >              ConstPointer;

  itkTypeMacro( BlendCostFunction, SingleValuedCostFunction );

  itkNewMacro( Self );

  typedef Superclass::MeasureType                 MeasureType;
  typedef Superclass::ParametersType              ParametersType;
  typedef Superclass::DerivativeType              DerivativeType;
  typedef itk::OrientedImage<pixelT, dimensionT>  ImageType;

  unsigned int GetNumberOfParameters( void ) const
    {
    return 4;
    }

  void SetImageTop( typename ImageType::Pointer _top )
    {
    m_ImageTop = _top;
    }

  void SetImageMiddle( typename ImageType::Pointer _middle )
    {
    m_ImageMiddle = _middle;
    }

  void SetImageBottom( typename ImageType::Pointer _bottom )
    {
    m_ImageBottom = _bottom;
    }

  void SetMaskMiddle( typename ImageType::Pointer _maskMiddle )
    {
    m_MaskMiddle = _maskMiddle;
    }
  void SetImageOutput( typename ImageType::Pointer _output )
    {
    m_ImageOutput = _output;
    }

  void GetDerivative( const ParametersType & params,
                      DerivativeType & deriv ) const
    {
    ParametersType unusedP = params;
    DerivativeType unusedD = deriv;
    return;
    }

  MeasureType GetValue( const ParametersType & params ) const
    {
    static unsigned int calls = 0;
    typedef itk::ImageRegionIterator< ImageType > ImageIteratorType;
    typedef itk::RecursiveGaussianImageFilter< ImageType, ImageType >
                                                  FilterType;

    if( params[3] < 0.2 )
      {
      return 10000;
      }

    typename FilterType::Pointer filterTop = FilterType::New();
    filterTop->SetInput( m_ImageTop );
    filterTop->SetSigma( params[3] );
    filterTop->Update();
    typename ImageType::Pointer imageTopB = filterTop->GetOutput();

    typename FilterType::Pointer filterBottom = FilterType::New();
    filterBottom->SetInput( m_ImageBottom );
    filterBottom->SetSigma( params[3] );
    filterBottom->Update();
    typename ImageType::Pointer imageBottomB = filterBottom->GetOutput();

    ImageIteratorType iterTopB( imageTopB,
                                imageTopB->GetLargestPossibleRegion() );
    ImageIteratorType iterBottomB( imageBottomB,
                                   imageBottomB->GetLargestPossibleRegion() );
    ImageIteratorType iterMiddle( m_ImageMiddle,
                                  m_ImageMiddle->GetLargestPossibleRegion() );
    ImageIteratorType iterOutput( m_ImageOutput,
                                  m_ImageOutput->GetLargestPossibleRegion() );
    while( !iterMiddle.IsAtEnd() )
      {
      float tf = params[0] * iterTopB.Get() +
        params[1] * iterBottomB.Get() +
        params[2];

      iterOutput.Set( iterMiddle.Get() - tf );

      ++iterMiddle;
      ++iterTopB;
      ++iterBottomB;
      ++iterOutput;
      }

    typedef itk::IdentityTransform< double, dimensionT >
      TransformType;
    typename TransformType::Pointer transform = TransformType::New();

    typedef itk::LinearInterpolateImageFunction< ImageType, double >
      InterpolatorType;
    typename InterpolatorType::Pointer interpolator =
      InterpolatorType::New();
    interpolator->SetInputImage( m_ImageOutput );

    typename ImageType::SizeType size;
    size = m_ImageMiddle->GetLargestPossibleRegion().GetSize();

    typedef itk::MeanSquaresImageToImageMetric< ImageType, ImageType >
      MetricType;
    typename MetricType::Pointer metric = MetricType::New();

    double samplingRate = 0.5;
    metric->SetFixedImage( m_MaskMiddle );
    metric->SetMovingImage( m_ImageOutput );
    metric->SetFixedImageRegion( m_MaskMiddle->
                                 GetLargestPossibleRegion() );
    metric->SetTransform( transform );
    metric->SetInterpolator( interpolator );
    metric->SetNumberOfSpatialSamples( size[0]*size[1]*samplingRate );
    metric->Initialize();
    metric->MultiThreadingInitialize();

    double result = metric->GetValue( transform->GetParameters() );

    std::cout << ++calls << ": "
              << params[0] << ", "
              << params[1] << ", "
              << params[2] << ", "
              << params[3]
              << " : result =" << result << std::endl;

    return result;
    }

protected:

  BlendCostFunction() {};
  virtual ~BlendCostFunction() {};

  void PrintSelf( std::ostream & os, Indent indent ) const
    {
    Superclass::PrintSelf( os, indent );
    }

private:

  BlendCostFunction( const Self & );
  void operator=( const Self & );

  typename ImageType::Pointer         m_ImageTop;
  typename ImageType::Pointer         m_ImageMiddle;
  typename ImageType::Pointer         m_ImageBottom;
  typename ImageType::Pointer         m_MaskMiddle;
  mutable typename ImageType::Pointer m_ImageOutput;

};

}; //namespace itk

template< class pixelT, unsigned int dimensionT >
int DoIt( int argc, char * argv[] )
{
  PARSE_ARGS;

  // The timeCollector is used to perform basic profiling of the components
  //   of your algorithm.
  itk::TimeProbesCollectorBase timeCollector;

  // CLIProgressReporter is used to communicate progress with Slicer GUI
  tube::CLIProgressReporter    progressReporter( "DeblendImagesUsingPrior",
                                                 CLPProcessInformation );
  progressReporter.Start();

  typedef float                                         PixelType;
  typedef itk::OrientedImage< PixelType,  dimensionT >  ImageType;

  /** Read input images */
  typename ImageType::Pointer imageTop;
  typename ImageType::Pointer imageMiddle;
  typename ImageType::Pointer imageBottom;
  typename ImageType::Pointer maskMiddle;

  timeCollector.Start("Read");
    {
    typedef itk::ImageFileReader< ImageType >   ReaderType;

    typename ReaderType::Pointer readerTop = ReaderType::New();
    typename ReaderType::Pointer readerMiddle = ReaderType::New();
    typename ReaderType::Pointer readerBottom = ReaderType::New();
    typename ReaderType::Pointer readerMask = ReaderType::New();

    //read input image
    readerTop->SetFileName( inputTop.c_str() );
    readerMiddle->SetFileName( inputMiddle.c_str() );
    readerBottom->SetFileName( inputBottom.c_str() );
    readerMask->SetFileName( inputMask.c_str() );

    try
      {
      readerTop->Update();
      }
    catch( itk::ExceptionObject & err )
      {
      tube::ErrorMessage( "Reading top. Exception caught: "
                          + std::string(err.GetDescription()) );
      timeCollector.Report();
      return EXIT_FAILURE;
      }

    try
      {
      readerMiddle->Update();
      }
    catch( itk::ExceptionObject & err )
      {
      tube::ErrorMessage( "Reading middle. Exception caught: "
                          + std::string(err.GetDescription()) );
      timeCollector.Report();
      return EXIT_FAILURE;
      }

    try
      {
      readerBottom->Update();
      }
    catch( itk::ExceptionObject & err )
      {
      tube::ErrorMessage( "Reading bottom. Exception caught: "
                          + std::string(err.GetDescription()) );
      timeCollector.Report();
      return EXIT_FAILURE;
      }

    try
      {
      readerMask->Update();
      }
    catch( itk::ExceptionObject & err )
      {
      tube::ErrorMessage( "Reading mask. Exception caught: "
                          + std::string(err.GetDescription()) );
      timeCollector.Report();
      return EXIT_FAILURE;
      }

    typedef itk::NormalizeImageFilter< ImageType, ImageType > NormFilterType;
    typename NormFilterType::Pointer normTop = NormFilterType::New();
    normTop->SetInput( readerTop->GetOutput() );
    normTop->Update();
    imageTop = normTop->GetOutput();

    typename NormFilterType::Pointer normMiddle = NormFilterType::New();
    normMiddle->SetInput( readerMiddle->GetOutput() );
    normMiddle->Update();
    imageMiddle = normMiddle->GetOutput();

    typename NormFilterType::Pointer normBottom = NormFilterType::New();
    normBottom->SetInput( readerBottom->GetOutput() );
    normBottom->Update();
    imageBottom = normBottom->GetOutput();

    typename NormFilterType::Pointer normMask = NormFilterType::New();
    normMask->SetInput( readerMask->GetOutput() );
    normMask->Update();
    maskMiddle = normMask->GetOutput();
    }
  progressReporter.Report( 0.1 );
  timeCollector.Stop("Read");

  typedef itk::BlendCostFunction< PixelType, dimensionT > BlendCostFunctionType;
  typedef itk::AmoebaOptimizer                            OptimizerType;
  typedef itk::ImageRegionIterator< ImageType >           ImageIteratorType;

  itk::Array<double> params(4);
  params[0] = alpha;
  params[1] = beta;
  params[2] = gamma;
  params[3] = sigma;

  typename BlendCostFunctionType::Pointer costFunc =
    BlendCostFunctionType::New();
  costFunc->SetImageTop( imageTop );
  costFunc->SetImageMiddle( imageMiddle );
  costFunc->SetImageBottom( imageBottom );
  costFunc->SetMaskMiddle( maskMiddle );

  OptimizerType::Pointer optimizer = OptimizerType::New();
  optimizer->SetMaximumNumberOfIterations( iterations );
  optimizer->SetMaximize( false );

  OptimizerType::ScalesType scales( 4 );
  scales[0] = 1.0 / 0.05;
  scales[1] = 1.0 / 0.05;
  scales[2] = 1.0 / 1;
  scales[3] = 1.0 / 0.2;
  optimizer->SetScales( scales );

  optimizer->SetCostFunction( costFunc );
  optimizer->SetInitialPosition( params );

  //
  // Generate output image
  //
  typename ImageType::Pointer imageOutput = ImageType::New();
  imageOutput->CopyInformation( imageMiddle );
  imageOutput->SetRegions( imageMiddle->GetLargestPossibleRegion() );
  imageOutput->Allocate();
  costFunc->SetImageOutput( imageOutput );

  optimizer->StartOptimization();

  params = optimizer->GetCurrentPosition();
  double result = costFunc->GetValue( params );
  std::cout << "Winning params = " << params
            << " Result = " << result << std::endl;

  typedef itk::ImageFileWriter< ImageType  >   ImageWriterType;
  typename ImageWriterType::Pointer writer = ImageWriterType::New();

  writer->SetFileName( outputMiddle.c_str() );
  writer->SetInput( imageOutput );
  writer->SetUseCompression( true );
  try
    {
    writer->Update();
    }
  catch( itk::ExceptionObject & err )
    {
    tube::ErrorMessage( "Writing volume. Exception caught: "
                        + std::string(err.GetDescription()) );
    timeCollector.Report();
    return EXIT_FAILURE;
    }

  progressReporter.Report( 1.0 );
  progressReporter.End( );

  timeCollector.Report();
  return EXIT_SUCCESS;
}

int main( int argc, char **argv )
{
  PARSE_ARGS;

  return tube::ParseArgsAndCallDoIt( inputMiddle, argc, argv );
}
<|endoftext|>


<commit_before>/**
 * @file    main.cpp
 * @brief   Debugger application's entry point.
 *
 * @author  Yonhgwhan, Noh (fixbrain@gmail.com)
 * @date    2015.11.17 11:17 created.
 * @copyright All rights reserved by Yonghwan, Noh.
**/

#include "stdafx.h"
#include <Windows.h>
#include <list>

#define     _pause  getchar()

/// @brief  debuggee process
typedef struct DEBUGGEE
{
    DWORD   process_id;
    HANDLE  process_handle;
    HANDLE  thread_handle;
    // todo 1, child thread  Ʈ ߰ϱ
}*PDEBUGGEE;

/// @brief
int main()
{
    //DEBUGGEE dbg[12] = { 0 };
    std::list<DEBUGGEE> dbg_list;

    // create process with /dbg
    STARTUPINFO			si = { 0 };
    PROCESS_INFORMATION pi = { 0 };
    //wchar_t* target = L"c:\\windows\\system32\\calc.exe";
    wchar_t* target = L".\\debuggee.exe";

    if (TRUE != CreateProcessW(
                    target,
                    NULL,
                    NULL,
                    NULL,
                    FALSE,
                    CREATE_NEW_CONSOLE | CREATE_SUSPENDED | DEBUG_PROCESS,
                    NULL,
                    NULL,
                    &si,
                    &pi))
    {
        printf("CreateProcess() failed. gle = %u \n", GetLastError());
        return -1;
    }
    printf("Press any key to continue...\n");
    _pause;
    ResumeThread(pi.hThread);

    // start debug loop
    DEBUG_EVENT debug_event = { 0 };
    while (true)
    {
        if (TRUE != WaitForDebugEvent(&debug_event, 100)) continue;

        DWORD continue_status = DBG_CONTINUE;

        switch (debug_event.dwDebugEventCode)
        {
        case CREATE_PROCESS_DEBUG_EVENT:
            {
                LPCREATE_PROCESS_DEBUG_INFO info = (LPCREATE_PROCESS_DEBUG_INFO)&debug_event.u.CreateProcessInfo;

                // debuggee Ҵ/߰
                DEBUGGEE dbg = { 0 };
                dbg.process_id = debug_event.dwProcessId;
                dbg.process_handle = info->hProcess;
                dbg.thread_handle = info->hThread;
                dbg_list.push_back(dbg);
                break;
            }
        default:
            break;
        }

        if (EXIT_PROCESS_DEBUG_EVENT == debug_event.dwDebugEventCode)
        {
            std::list<DEBUGGEE>::iterator it = dbg_list.begin();
            for (; it != dbg_list.end(); ++it)
            {
                if (it->process_id == debug_event.dwProcessId)
                {
                    ///
                    printf("proc handle=0x%p \n", it->process_handle);
                    printf("main thrad handle=0x%p \n", it->thread_handle);
                    break;  // debuggee  Ǹ, debug loop   Ѵ.
                }
            }
            dbg_list.erase(it);
        }

        ContinueDebugEvent(
            debug_event.dwProcessId,
            debug_event.dwThreadId,
            continue_status);

        if (dbg_list.empty())
        {
            break;
        }

    }

    printf("\nPress any key to terminate...\n");

    // todo 2,   ϱ
    _pause;

    return 0;
}<commit_msg>thread create / exit 이벤트 처리<commit_after>/**
 * @file    main.cpp
 * @brief   Debugger application's entry point.
 *
 * @author  Yonhgwhan, Noh (fixbrain@gmail.com)
 * @date    2015.11.17 11:17 created.
 * @copyright All rights reserved by Yonghwan, Noh.
**/

#include "stdafx.h"
#include <Windows.h>
#include <Psapi.h>
#include <list>
#include <string>
#include <sal.h>

#define     _pause  getchar()

const char* exception_code_str(_In_ DWORD exception_code);
bool get_mapped_file_name(
    _In_ HANDLE process_handle,
    _In_ const void* mapped_addr,
    _Out_ std::wstring& file_name
);

bool get_filepath_by_handle(
    _In_ HANDLE file_handle,
    _Out_ std::wstring& file_path
);

typedef class Thread
{
public:
    Thread() {}
    ~Thread() {}

    DWORD   thread_id;
    HANDLE  hThread;
    LPVOID  lpThreadLocalBase;
    LPTHREAD_START_ROUTINE lpStartAddress;

} *PThread;

/// @brief  debuggee process
typedef class Debuggee
{
public:
    Debuggee()
    {
    }
    ~Debuggee() {}

    DWORD   process_id;
    HANDLE  process_handle;
    HANDLE  thread_handle;
    std::wstring    image;

    std::list<Thread>   threads;
}*PDebuggee;

/// @brief
int main()
{
    //Debuggee dbg[12] = { 0 };
    std::list<Debuggee> dbg_list;

    // create process with /dbg
    STARTUPINFO			si = { 0 };
    PROCESS_INFORMATION pi = { 0 };
    //wchar_t* target = L"c:\\windows\\system32\\calc.exe";
    wchar_t* target = L".\\debuggee.exe";

    if (TRUE != CreateProcessW(
                    target,
                    NULL,
                    NULL,
                    NULL,
                    FALSE,
                    CREATE_NEW_CONSOLE | CREATE_SUSPENDED | DEBUG_PROCESS,
                    NULL,
                    NULL,
                    &si,
                    &pi))
    {
        printf("CreateProcess() failed. gle = %u \n", GetLastError());
        return -1;
    }
    printf("Press any key to continue...\n");
    _pause;
    ResumeThread(pi.hThread);

    // start debug loop
    DEBUG_EVENT debug_event = { 0 };
    while (true)
    {
        if (TRUE != WaitForDebugEvent(&debug_event, 100)) continue;

        DWORD continue_status = DBG_CONTINUE;

        switch (debug_event.dwDebugEventCode)
        {
        case CREATE_PROCESS_DEBUG_EVENT:
            {
                LPCREATE_PROCESS_DEBUG_INFO info = (LPCREATE_PROCESS_DEBUG_INFO)&debug_event.u.CreateProcessInfo;

                std::wstring image;
                if (true != get_filepath_by_handle(info->hFile, image))
                {
                    image = L"unknown image path";
                }

                // debuggee Ҵ/߰
                Debuggee dbg;
                dbg.process_id = debug_event.dwProcessId;
                dbg.process_handle = info->hProcess;
                dbg.thread_handle = info->hThread;
                dbg.image = image;
                dbg_list.push_back(dbg);
                break;
            }

        case CREATE_THREAD_DEBUG_EVENT:
            {
                LPCREATE_THREAD_DEBUG_INFO info = (LPCREATE_THREAD_DEBUG_INFO)&debug_event.u.CreateThread;
                Thread thread;
                thread.thread_id = GetThreadId(info->hThread);
                thread.hThread = info->hThread;
                thread.lpStartAddress = info->lpStartAddress;
                thread.lpThreadLocalBase = info->lpThreadLocalBase;

                for (auto dbg : dbg_list)
                {
                    if (dbg.process_id == debug_event.dwProcessId)
                    {
                        dbg.threads.push_back(thread);
                    }
                }
                break;
            }
        case EXIT_THREAD_DEBUG_EVENT:
            {
                LPEXIT_THREAD_DEBUG_INFO info = (LPEXIT_THREAD_DEBUG_INFO)&debug_event.u.ExitThread;
                for (auto dbg : dbg_list)
                {
                    if (dbg.process_id == debug_event.dwProcessId)
                    {
                        std::list<Thread>::iterator tit = dbg.threads.begin();
                        for (; tit != dbg.threads.end(); ++tit)
                        {
                            if (tit->thread_id == debug_event.dwThreadId)
                            {
                                dbg.threads.erase(tit);
                                break;
                            }
                        }
                    }
                }
                break;
            }
        default:
            break;
        }

        if (EXIT_PROCESS_DEBUG_EVENT == debug_event.dwDebugEventCode)
        {
            std::list<Debuggee>::iterator it = dbg_list.begin();
            for (; it != dbg_list.end(); ++it)
            {
                if (it->process_id == debug_event.dwProcessId)
                {
                    ///
                    printf("proc handle=0x%p \n", it->process_handle);
                    printf("main thrad handle=0x%p \n", it->thread_handle);
                    break;  // debuggee  Ǹ, debug loop   Ѵ.
                }
            }
            dbg_list.erase(it);
        }

        ContinueDebugEvent(
            debug_event.dwProcessId,
            debug_event.dwThreadId,
            continue_status);

        if (dbg_list.empty())
        {
            break;
        }

    }

    printf("\nPress any key to terminate...\n");

    // todo 2,   ϱ
    _pause;

    return 0;
}

const char* exception_code_str(_In_ DWORD exception_code)
{
    switch (exception_code)
    {
    case EXCEPTION_ACCESS_VIOLATION: return "EXCEPTION_ACCESS_VIOLATION";
    case EXCEPTION_DATATYPE_MISALIGNMENT: return "EXCEPTION_DATATYPE_MISALIGNMENT";
    case EXCEPTION_BREAKPOINT: return "EXCEPTION_BREAKPOINT";
    case EXCEPTION_SINGLE_STEP: return "EXCEPTION_SINGLE_STEP";
    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
    case EXCEPTION_FLT_DENORMAL_OPERAND: return "EXCEPTION_FLT_DENORMAL_OPERAND";
    case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
    case EXCEPTION_FLT_INEXACT_RESULT: return "EXCEPTION_FLT_INEXACT_RESULT";
    case EXCEPTION_FLT_INVALID_OPERATION: return "EXCEPTION_FLT_INVALID_OPERATION";
    case EXCEPTION_FLT_OVERFLOW: return "EXCEPTION_FLT_OVERFLOW";
    case EXCEPTION_FLT_STACK_CHECK: return "EXCEPTION_FLT_STACK_CHECK";
    case EXCEPTION_FLT_UNDERFLOW: return "EXCEPTION_FLT_UNDERFLOW";
    case EXCEPTION_INT_DIVIDE_BY_ZERO: return "EXCEPTION_INT_DIVIDE_BY_ZERO";
    case EXCEPTION_INT_OVERFLOW: return "EXCEPTION_INT_OVERFLOW";
    case EXCEPTION_PRIV_INSTRUCTION: return "EXCEPTION_PRIV_INSTRUCTION";
    case EXCEPTION_IN_PAGE_ERROR: return "EXCEPTION_IN_PAGE_ERROR";
    case EXCEPTION_ILLEGAL_INSTRUCTION: return "EXCEPTION_ILLEGAL_INSTRUCTION";
    case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
    case EXCEPTION_STACK_OVERFLOW: return "EXCEPTION_STACK_OVERFLOW";
    case EXCEPTION_INVALID_DISPOSITION: return "EXCEPTION_INVALID_DISPOSITION";
    case EXCEPTION_GUARD_PAGE: return "EXCEPTION_GUARD_PAGE";
    case EXCEPTION_INVALID_HANDLE: return "EXCEPTION_INVALID_HANDLE";
    //case EXCEPTION_POSSIBLE_DEADLOCK: return "EXCEPTION_POSSIBLE_DEADLOCK";
    default:
        return "UNKNOWN EXCEPTION CODE";
    }

}

/**
 * @brief	file_handle  file path  ϴ Լ
 * @param
 * @see		http://msdn.microsoft.com/en-us/library/windows/desktop/aa366789(v=vs.85).aspx
 * @remarks	NtQueryObject()  ϴ°    ⵵ ,   ߻
 * @remarks Ȯغ
 * @code
 * @endcode
 * @return
**/
bool
get_filepath_by_handle(
	_In_ HANDLE file_handle,
	_Out_ std::wstring& file_path
	)
{
	_ASSERTE(NULL != file_handle);
	_ASSERTE(INVALID_HANDLE_VALUE != file_handle);
	if (NULL == file_handle || INVALID_HANDLE_VALUE == file_handle) return false;

	LARGE_INTEGER file_size = {0};
	if (TRUE != GetFileSizeEx(file_handle, &file_size))
	{
		return false;
	}

	if (0 == file_size.QuadPart)
	{
		return false;
	}

    bool succeeded = false;
    HANDLE hcfm = NULL;
    LPVOID mvo = NULL;

    do
    {
        hcfm = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 1, NULL);
	    if (NULL == hcfm)
	    {
            break;
	    }

        mvo = MapViewOfFile(hcfm, FILE_MAP_READ, 0, 0, 1);
	    if (NULL == mvo)
	    {
            break;
	    }

	    std::wstring nt_device_name;
	    if (true != get_mapped_file_name(
					    GetCurrentProcess(),
					    mvo,
					    nt_device_name))
	    {
            break;
	    }

	    /*if (true != nt_name_to_dos_name(nt_device_name.c_str(), file_path))
	    {
		    log_err "nt_name_to_dos_name( nt name = %s )", nt_device_name.c_str() log_end
		    return false;
	    }*/
        file_path = nt_device_name.c_str();
        succeeded = true;
    } while (false);

    if (NULL != hcfm) CloseHandle(hcfm);
    if (NULL != mvo) UnmapViewOfFile(mvo);
    return succeeded;
}

/**
 * @brief	wrapper function for GetMappedFileName()
 * @param
 * @see		http://msdn.microsoft.com/en-us/library/windows/desktop/ms683195(v=vs.85).aspx
 * @remarks
 * @code
 * @endcode
 * @return	true if succeeded.
 * @return	file_name is nt device name (e.g. Device\HarddiskVolume2\Windows\System32\drivers\etc\hosts)
 * @return	if you want use dos device name, use nt_name_to_dos_name() function.
**/
bool
get_mapped_file_name(
	_In_ HANDLE process_handle,
	_In_ const void* mapped_addr,
	_Out_ std::wstring& file_name
	)
{
	bool		ret = false;
	DWORD		ret_cch_buf = 0;
	DWORD		cch_buf = MAX_PATH;
	wchar_t*	buf = NULL;

	for(;;)
	{
		if (NULL != buf) free(buf);

		buf = (wchar_t*) malloc((cch_buf + 1) * sizeof(wchar_t));	// add NULL
		if (NULL == buf)
		{
			//log_err
			//	"insufficient memory, malloc( %u )",
			//	(cch_buf + 1) * sizeof(wchar_t)
			//log_end
			return false;
		}

		ret_cch_buf = GetMappedFileNameW(
							process_handle,
							const_cast<void*>(mapped_addr),
							buf,
							cch_buf
							);
		if (0 == ret_cch_buf)
		{
			//log_err
			//	"GetMappedFileNameW( process handle = 0x%08x, addr = 0x%p ), gle = %u",
			//	process_handle,
			//	mapped_addr,
			//	GetLastError()
			//log_end

			break;
		}

		if (ret_cch_buf < cch_buf)
		{
			// OK!
			ret = true;
			buf[ret_cch_buf] = L'\0';
			break;
		}
		else if (ret_cch_buf == cch_buf)
		{
			// we need more buffer
			cch_buf *= 2;
			continue;
		}
		else
		{
			//log_err
			//	"unexpected ret_cch_buf(%u) : cch_buf(%u), GetMappedFileNameW()",
			//	ret_cch_buf,
			//	cch_buf
			//log_end
			break;
		}
	}

	if(true == ret) file_name = buf;

	free(buf); buf = NULL;
	return ret;
}<|endoftext|>


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

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  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 "ModuleVolume.h"

#include "DataSource.h"
#include "Utilities.h"

#include <vtkColorTransferFunction.h>
#include <vtkImageData.h>
#include <vtkImageShiftScale.h>
#include <vtkNew.h>
#include <vtkPiecewiseFunction.h>
#include <vtkSmartPointer.h>
#include <vtkSmartVolumeMapper.h>
#include <vtkTrivialProducer.h>
#include <vtkVector.h>
#include <vtkView.h>
#include <vtkVolume.h>
#include <vtkVolumeProperty.h>

#include <pqProxiesWidget.h>
#include <vtkPVRenderView.h>
#include <vtkSMPVRepresentationProxy.h>
#include <vtkSMParaViewPipelineControllerWithRendering.h>
#include <vtkSMPropertyHelper.h>
#include <vtkSMSessionProxyManager.h>
#include <vtkSMSourceProxy.h>
#include <vtkSMViewProxy.h>

#include <QCheckBox>
#include <QVBoxLayout>

namespace tomviz {

ModuleVolume::ModuleVolume(QObject* parentObject) : Superclass(parentObject)
{
}

ModuleVolume::~ModuleVolume()
{
  this->finalize();
}

QIcon ModuleVolume::icon() const
{
  return QIcon(":/pqWidgets/Icons/pqVolumeData16.png");
}

bool ModuleVolume::initialize(DataSource* data, vtkSMViewProxy* vtkView)
{
  if (!this->Superclass::initialize(data, vtkView)) {
    return false;
  }

  vtkNew<vtkImageShiftScale> t;

  vtkTrivialProducer* trv =
    vtkTrivialProducer::SafeDownCast(data->producer()->GetClientSideObject());
  vtkImageData* im = vtkImageData::SafeDownCast(trv->GetOutputDataObject(0));

  t->SetInputData(im);

  m_volumeMapper->SetInputConnection(t->GetOutputPort());
  m_volume->SetMapper(m_volumeMapper.Get());
  m_volume->SetProperty(m_volumeProperty.Get());

  this->updateColorMap();

  m_view = vtkPVRenderView::SafeDownCast(vtkView->GetClientSideView());
  m_view->AddPropToRenderer(m_volume.Get());

  return true;
}

void ModuleVolume::updateColorMap()
{
  m_volumeProperty->SetScalarOpacity(
    vtkPiecewiseFunction::SafeDownCast(opacityMap()->GetClientSideObject()));
  m_volumeProperty->SetColor(
    vtkColorTransferFunction::SafeDownCast(colorMap()->GetClientSideObject()));

  // BUG: volume mappers don't update property when LUT is changed and has an
  // older Mtime. Fix for now by forcing the LUT to update.
  vtkObject::SafeDownCast(this->colorMap()->GetClientSideObject())->Modified();
}

bool ModuleVolume::finalize()
{
  if (m_view) {
    m_view->RemovePropFromRenderer(m_volume.Get());
  }

  return true;
}

bool ModuleVolume::setVisibility(bool val)
{
  m_volume->SetVisibility(val ? 1 : 0);
  return true;
}

bool ModuleVolume::visibility() const
{
  return m_volume->GetVisibility() != 0;
}

bool ModuleVolume::serialize(pugi::xml_node&) const
{
  return false;
}

bool ModuleVolume::deserialize(const pugi::xml_node& ns)
{
  return this->Superclass::deserialize(ns);
}

void ModuleVolume::addToPanel(QWidget* panel)
{
  if (panel->layout()) {
    delete panel->layout();
  }

  QVBoxLayout* layout = new QVBoxLayout;
  QCheckBox* lighting = new QCheckBox("Enable lighting");
  layout->addWidget(lighting);
  panel->setLayout(layout);
  QCheckBox* maxIntensity = new QCheckBox("Maximum intensity");
  layout->addWidget(maxIntensity);
  layout->addStretch();

  lighting->setChecked(m_volumeProperty->GetShade() == 1);
  maxIntensity->setChecked(m_volumeMapper->GetBlendMode() ==
                           vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND);

  connect(lighting, SIGNAL(clicked(bool)), SLOT(setLighting(bool)));
  connect(maxIntensity, SIGNAL(clicked(bool)), SLOT(setMaximumIntensity(bool)));
}

void ModuleVolume::dataSourceMoved(double newX, double newY, double newZ)
{
  vtkVector3d pos(newX, newY, newZ);
  m_volume->SetPosition(pos.GetData());
}

bool ModuleVolume::isProxyPartOfModule(vtkSMProxy*)
{
  return false;
}

std::string ModuleVolume::getStringForProxy(vtkSMProxy*)
{
  qWarning("Unknown proxy passed to module volume in save animation");
  return "";
}

vtkSMProxy* ModuleVolume::getProxyForString(const std::string&)
{
  return nullptr;
}

void ModuleVolume::setLighting(bool val)
{
  m_volumeProperty->SetShade(val ? 1 : 0);
  m_volumeProperty->SetAmbient(0.0);
  m_volumeProperty->SetDiffuse(1.0);
  m_volumeProperty->SetSpecularPower(100.0);
  emit renderNeeded();
}

void ModuleVolume::setMaximumIntensity(bool val)
{
  if (val) {
    m_volumeMapper->SetBlendMode(vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND);
  } else {
    m_volumeMapper->SetBlendMode(vtkVolumeMapper::COMPOSITE_BLEND);
  }
  emit renderNeeded();
}

} // end of namespace tomviz
<commit_msg>Simple serialize/deserialize for the state file<commit_after>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  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 "ModuleVolume.h"

#include "DataSource.h"
#include "Utilities.h"

#include <vtkColorTransferFunction.h>
#include <vtkImageData.h>
#include <vtkImageShiftScale.h>
#include <vtkNew.h>
#include <vtkPiecewiseFunction.h>
#include <vtkSmartPointer.h>
#include <vtkSmartVolumeMapper.h>
#include <vtkTrivialProducer.h>
#include <vtkVector.h>
#include <vtkView.h>
#include <vtkVolume.h>
#include <vtkVolumeProperty.h>

#include <pqProxiesWidget.h>
#include <vtkPVRenderView.h>
#include <vtkSMPVRepresentationProxy.h>
#include <vtkSMParaViewPipelineControllerWithRendering.h>
#include <vtkSMPropertyHelper.h>
#include <vtkSMSessionProxyManager.h>
#include <vtkSMSourceProxy.h>
#include <vtkSMViewProxy.h>

#include <QCheckBox>
#include <QVBoxLayout>

namespace tomviz {

using pugi::xml_attribute;
using pugi::xml_node;

ModuleVolume::ModuleVolume(QObject* parentObject) : Superclass(parentObject)
{
}

ModuleVolume::~ModuleVolume()
{
  this->finalize();
}

QIcon ModuleVolume::icon() const
{
  return QIcon(":/pqWidgets/Icons/pqVolumeData16.png");
}

bool ModuleVolume::initialize(DataSource* data, vtkSMViewProxy* vtkView)
{
  if (!this->Superclass::initialize(data, vtkView)) {
    return false;
  }

  vtkNew<vtkImageShiftScale> t;

  vtkTrivialProducer* trv =
    vtkTrivialProducer::SafeDownCast(data->producer()->GetClientSideObject());
  vtkImageData* im = vtkImageData::SafeDownCast(trv->GetOutputDataObject(0));

  t->SetInputData(im);

  m_volumeMapper->SetInputConnection(t->GetOutputPort());
  m_volume->SetMapper(m_volumeMapper.Get());
  m_volume->SetProperty(m_volumeProperty.Get());

  this->updateColorMap();

  m_view = vtkPVRenderView::SafeDownCast(vtkView->GetClientSideView());
  m_view->AddPropToRenderer(m_volume.Get());

  return true;
}

void ModuleVolume::updateColorMap()
{
  m_volumeProperty->SetScalarOpacity(
    vtkPiecewiseFunction::SafeDownCast(opacityMap()->GetClientSideObject()));
  m_volumeProperty->SetColor(
    vtkColorTransferFunction::SafeDownCast(colorMap()->GetClientSideObject()));

  // BUG: volume mappers don't update property when LUT is changed and has an
  // older Mtime. Fix for now by forcing the LUT to update.
  vtkObject::SafeDownCast(this->colorMap()->GetClientSideObject())->Modified();
}

bool ModuleVolume::finalize()
{
  if (m_view) {
    m_view->RemovePropFromRenderer(m_volume.Get());
  }

  return true;
}

bool ModuleVolume::setVisibility(bool val)
{
  m_volume->SetVisibility(val ? 1 : 0);
  return true;
}

bool ModuleVolume::visibility() const
{
  return m_volume->GetVisibility() != 0;
}

bool ModuleVolume::serialize(pugi::xml_node& ns) const
{
  xml_node rootNode = ns.append_child("properties");
  xml_node lightingNode = rootNode.append_child("lighting");
  lightingNode.append_attribute("enabled") = m_volumeProperty->GetShade() == 1;
  xml_node maxIntensityNode = rootNode.append_child("maxIntensity");
  bool maxIntensity =
    m_volumeMapper->GetBlendMode() == vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND;
  maxIntensityNode.append_attribute("enabled") = maxIntensity;
  return true;
}

bool ModuleVolume::deserialize(const pugi::xml_node& ns)
{
  xml_node rootNode = ns.child("properties");
  if (!rootNode) {
    return false;
  }

  xml_node node = rootNode.child("lighting");
  if (node) {
    xml_attribute att = node.attribute("enabled");
    if (att) {
      setLighting(att.as_bool());
    }
  }
  node = rootNode.child("maxIntensity");
  if (node) {
    xml_attribute att = node.attribute("enabled");
    if (att) {
      setMaximumIntensity(att.as_bool());
    }
  }

  return this->Superclass::deserialize(ns);
}

void ModuleVolume::addToPanel(QWidget* panel)
{
  if (panel->layout()) {
    delete panel->layout();
  }

  QVBoxLayout* layout = new QVBoxLayout;
  QCheckBox* lighting = new QCheckBox("Enable lighting");
  layout->addWidget(lighting);
  panel->setLayout(layout);
  QCheckBox* maxIntensity = new QCheckBox("Maximum intensity");
  layout->addWidget(maxIntensity);
  layout->addStretch();

  lighting->setChecked(m_volumeProperty->GetShade() == 1);
  maxIntensity->setChecked(m_volumeMapper->GetBlendMode() ==
                           vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND);

  connect(lighting, SIGNAL(clicked(bool)), SLOT(setLighting(bool)));
  connect(maxIntensity, SIGNAL(clicked(bool)), SLOT(setMaximumIntensity(bool)));
}

void ModuleVolume::dataSourceMoved(double newX, double newY, double newZ)
{
  vtkVector3d pos(newX, newY, newZ);
  m_volume->SetPosition(pos.GetData());
}

bool ModuleVolume::isProxyPartOfModule(vtkSMProxy*)
{
  return false;
}

std::string ModuleVolume::getStringForProxy(vtkSMProxy*)
{
  qWarning("Unknown proxy passed to module volume in save animation");
  return "";
}

vtkSMProxy* ModuleVolume::getProxyForString(const std::string&)
{
  return nullptr;
}

void ModuleVolume::setLighting(bool val)
{
  m_volumeProperty->SetShade(val ? 1 : 0);
  m_volumeProperty->SetAmbient(0.0);
  m_volumeProperty->SetDiffuse(1.0);
  m_volumeProperty->SetSpecularPower(100.0);
  emit renderNeeded();
}

void ModuleVolume::setMaximumIntensity(bool val)
{
  if (val) {
    m_volumeMapper->SetBlendMode(vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND);
  } else {
    m_volumeMapper->SetBlendMode(vtkVolumeMapper::COMPOSITE_BLEND);
  }
  emit renderNeeded();
}

} // end of namespace tomviz
<|endoftext|>


<commit_before>#include "Generation_Type.h"

#include "../../Util/STD_Util.h"
#include "../../Maths/General_Maths.h"

bool World_Generation_Type::BiomeRange::isThisBiome(int biomeKey)
{
/*
    std::cout   << "\nKey: "      << biomeKey
                << "\nCompare: "  << (int)m_compare
                << "\nMin"        << m_min
                << "\nMax"        << m_max
                << "\n\n";
*/
    switch (m_compare)
    {
        case Compare::Greater:
            return biomeKey >= m_max;

        case Compare::Less:
            return biomeKey <= m_max;

        case Compare::Range:
            return Maths::inRange(biomeKey, m_min, m_max);
    }
    return false;
}

const Biome& World_Generation_Type::BiomeRange::getBiome() const
{
    return m_biome;
}

World_Generation_Type::World_Generation_Type(const std::string& folderName)
:   m_folder    (folderName)
{
    std::string full = "Data/WorldGen/" + m_folder + "/Info.biome";
    Loader::load(full);
}

const Noise::Data& World_Generation_Type::getBiomeMapNoise()
{
    return m_biomeNoise;
}

const Biome& World_Generation_Type::getBiome(int biomeKey)
{
    for (auto& biome : m_biomes)
    {
        if (biome.isThisBiome(biomeKey))
        {
            return biome.getBiome();
        }
    }
    throw std::runtime_error("Unable to get biome: " + std::to_string(biomeKey));
    ///@TODO Return an "error biome"
}

bool World_Generation_Type::parseLine(const std::string& line, std::ifstream& inFile)
{
    if (areStringsSame(line, "Noise"))
    {
        loadNoise(inFile);
    }
    else if (areStringsSame(line, "Biome"))
    {
        loadBiome(inFile);
    }
    else
    {
        return false;
    }
    return true;
}

void World_Generation_Type::loadNoise(std::ifstream& inFile)
{
    int octaves,
        amplitude,
        heightOffset;

    float   roughness,
            smoothness;

    inFile >> octaves >> amplitude >> roughness >> smoothness >> heightOffset;

    m_biomeNoise = {octaves, amplitude, roughness, smoothness, heightOffset};
}

void World_Generation_Type::loadBiome(std::ifstream& inFile)
{
    std::string compareString;
    std::string biomeName;

    Compare compare;
    int     minVal = 0;
    int     maxVal = 0;

    std::getline(inFile, biomeName);
    std::getline(inFile, compareString);

    if (areStringsSame(compareString, "Range"))
    {
        compare = Compare::Range;
    }
    else if (areStringsSame(compareString, "Greater"))
    {
        compare = Compare::Greater;
    }
    else if (areStringsSame(compareString, "Less"))
    {
        compare = Compare::Less;
    }
    else
    {
        throw std::runtime_error("Token: " + compareString + " not known.");
    }

    switch (compare)
    {
        case Compare::Greater:
        case Compare::Less:
            inFile >> maxVal;
            break;

        case Compare::Range:
            inFile >> minVal >> maxVal;
            break;
    }

    Biome b(std::move(biomeName), m_folder);

    std::cout << "Add biome\n";
    m_biomes.emplace_back(minVal, maxVal, compare, std::move(b));
}

<commit_msg>Remove some random cout statements<commit_after>#include "Generation_Type.h"

#include "../../Util/STD_Util.h"
#include "../../Maths/General_Maths.h"

bool World_Generation_Type::BiomeRange::isThisBiome(int biomeKey)
{
    switch (m_compare)
    {
        case Compare::Greater:
            return biomeKey >= m_max;

        case Compare::Less:
            return biomeKey <= m_max;

        case Compare::Range:
            return Maths::inRange(biomeKey, m_min, m_max);
    }
    return false;
}

const Biome& World_Generation_Type::BiomeRange::getBiome() const
{
    return m_biome;
}

World_Generation_Type::World_Generation_Type(const std::string& folderName)
:   m_folder    (folderName)
{
    std::string full = "Data/WorldGen/" + m_folder + "/Info.biome";
    Loader::load(full);
}

const Noise::Data& World_Generation_Type::getBiomeMapNoise()
{
    return m_biomeNoise;
}

const Biome& World_Generation_Type::getBiome(int biomeKey)
{
    for (auto& biome : m_biomes)
    {
        if (biome.isThisBiome(biomeKey))
        {
            return biome.getBiome();
        }
    }
    throw std::runtime_error("Unable to get biome: " + std::to_string(biomeKey));
    ///@TODO Return an "error biome"
}

bool World_Generation_Type::parseLine(const std::string& line, std::ifstream& inFile)
{
    if (areStringsSame(line, "Noise"))
    {
        loadNoise(inFile);
    }
    else if (areStringsSame(line, "Biome"))
    {
        loadBiome(inFile);
    }
    else
    {
        return false;
    }
    return true;
}

void World_Generation_Type::loadNoise(std::ifstream& inFile)
{
    int octaves,
        amplitude,
        heightOffset;

    float   roughness,
            smoothness;

    inFile >> octaves >> amplitude >> roughness >> smoothness >> heightOffset;

    m_biomeNoise = {octaves, amplitude, roughness, smoothness, heightOffset};
}

void World_Generation_Type::loadBiome(std::ifstream& inFile)
{
    std::string compareString;
    std::string biomeName;

    Compare compare;
    int     minVal = 0;
    int     maxVal = 0;

    std::getline(inFile, biomeName);
    std::getline(inFile, compareString);

    if (areStringsSame(compareString, "Range"))
    {
        compare = Compare::Range;
    }
    else if (areStringsSame(compareString, "Greater"))
    {
        compare = Compare::Greater;
    }
    else if (areStringsSame(compareString, "Less"))
    {
        compare = Compare::Less;
    }
    else
    {
        throw std::runtime_error("Token: " + compareString + " not known.");
    }

    switch (compare)
    {
        case Compare::Greater:
        case Compare::Less:
            inFile >> maxVal;
            break;

        case Compare::Range:
            inFile >> minVal >> maxVal;
            break;
    }

    Biome b(std::move(biomeName), m_folder);

    m_biomes.emplace_back(minVal, maxVal, compare, std::move(b));
}

<|endoftext|>


<commit_before><commit_msg>Added extra variables to the tree for the c-deuteron part. Also fixed a bug in PrepareTracks, changing cast to int to floor.<commit_after><|endoftext|>


<commit_before><commit_msg>change variable name in AddTaskSigmacTopK0Spi.C<commit_after><|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

Copyright (c) 2000-2014 Torus Knot Software Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "OgreShaderPrecompiledHeaders.h"

#ifdef RTSHADER_SYSTEM_BUILD_EXT_SHADERS
#define HS_DATA_BIND_NAME "HS_SRS_DATA"

namespace Ogre {

namespace RTShader {

/************************************************************************/
/*                                                                      */
/************************************************************************/
DualQuaternionSkinning::DualQuaternionSkinning() : HardwareSkinningTechnique()
{
}

//-----------------------------------------------------------------------
bool DualQuaternionSkinning::resolveParameters(ProgramSet* programSet)
{
    Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
    Function* vsMain = vsProgram->getEntryPointFunction();

    //if needed mark this vertex program as hardware skinned
    if (mDoBoneCalculations == true)
    {
        vsProgram->setSkeletalAnimationIncluded(true);
    }

    //
    // get the parameters we need whether we are doing bone calculations or not
    //
    // Note: in order to be consistent we will always output position, normal,
    // tangent and binormal in both object and world space. And output position
    // in projective space to cover the responsibility of the transform stage

    //input param
    mParamInPosition = vsMain->resolveInputParameter(Parameter::SPC_POSITION_OBJECT_SPACE);

    if(mDoLightCalculations)
        mParamInNormal = vsMain->resolveInputParameter(Parameter::SPC_NORMAL_OBJECT_SPACE);
    //mParamInBiNormal = vsMain->resolveInputParameter(Parameter::SPS_BINORMAL, 0, Parameter::SPC_BINORMAL_OBJECT_SPACE, GCT_FLOAT3);
    //mParamInTangent = vsMain->resolveInputParameter(Parameter::SPS_TANGENT, 0, Parameter::SPC_TANGENT_OBJECT_SPACE, GCT_FLOAT3);

    //local param
    mParamLocalBlendPosition = vsMain->resolveLocalParameter("BlendedPosition", GCT_FLOAT3);
    mParamLocalNormalWorld = vsMain->resolveLocalParameter(Parameter::SPC_NORMAL_WORLD_SPACE);
    //mParamLocalTangentWorld = vsMain->resolveLocalParameter(Parameter::SPS_TANGENT, 0, Parameter::SPC_TANGENT_WORLD_SPACE, GCT_FLOAT3);
    //mParamLocalBinormalWorld = vsMain->resolveLocalParameter(Parameter::SPS_BINORMAL, 0, Parameter::SPC_BINORMAL_WORLD_SPACE, GCT_FLOAT3);

    //output param
    mParamOutPositionProj = vsMain->resolveOutputParameter(Parameter::SPC_POSITION_PROJECTIVE_SPACE);

    if (mDoBoneCalculations == true)
    {
        //input parameters
        mParamInIndices = vsMain->resolveInputParameter(Parameter::SPC_BLEND_INDICES);
        mParamInWeights = vsMain->resolveInputParameter(Parameter::SPC_BLEND_WEIGHTS);
        mParamInWorldMatrices = vsProgram->resolveParameter(GpuProgramParameters::ACT_WORLD_DUALQUATERNION_ARRAY_2x4, mBoneCount);
        mParamInInvWorldMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_INVERSE_WORLD_MATRIX);
        mParamInViewProjMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_VIEWPROJ_MATRIX);

        mParamTempWorldMatrix = vsMain->resolveLocalParameter("worldMatrix", GCT_MATRIX_2X4);
        mParamBlendDQ = vsMain->resolveLocalParameter("blendDQ", GCT_MATRIX_2X4);
        mParamInitialDQ = vsMain->resolveLocalParameter("initialDQ", GCT_MATRIX_2X4);

        if (ShaderGenerator::getSingleton().getTargetLanguage() == "hlsl")
        {
            //set hlsl shader to use row-major matrices instead of column-major.
            //it enables the use of auto-bound 3x4 matrices in generated hlsl shader.
            vsProgram->setUseColumnMajorMatrices(false);
        }

        if(mScalingShearingSupport)
        {
            mParamInScaleShearMatrices = vsProgram->resolveParameter(GpuProgramParameters::ACT_WORLD_SCALE_SHEAR_MATRIX_ARRAY_3x4, mBoneCount);
            mParamBlendS = vsMain->resolveLocalParameter("blendS", GCT_MATRIX_3X4);
            mParamTempFloat3x3 = vsMain->resolveLocalParameter("TempVal3x3", GCT_MATRIX_3X3);
            mParamTempFloat3x4 = vsMain->resolveLocalParameter("TempVal3x4", GCT_MATRIX_3X4);
        }

        mParamTempFloat2x4 = vsMain->resolveLocalParameter("TempVal2x4", GCT_MATRIX_2X4);
        mParamTempFloat4 = vsMain->resolveLocalParameter("TempVal4", GCT_FLOAT4);
        mParamTempFloat3 = vsMain->resolveLocalParameter("TempVal3", GCT_FLOAT3);
    }
    else
    {
        mParamInWorldMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_WORLD_MATRIX);
        mParamInWorldViewProjMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
    }
    return true;
}

//-----------------------------------------------------------------------
bool DualQuaternionSkinning::resolveDependencies(ProgramSet* programSet)
{
    Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
    vsProgram->addDependency(FFP_LIB_COMMON);
    vsProgram->addDependency(FFP_LIB_TRANSFORM);
    vsProgram->addDependency(SGX_LIB_DUAL_QUATERNION);

    return true;
}

//-----------------------------------------------------------------------
bool DualQuaternionSkinning::addFunctionInvocations(ProgramSet* programSet)
{
    Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
    Function* vsMain = vsProgram->getEntryPointFunction();

    //add functions to calculate position data in world, object and projective space
    addPositionCalculations(vsMain);

    //add functions to calculate normal and normal related data in world and object space
    if(mDoLightCalculations)
        addNormalRelatedCalculations(vsMain, mParamInNormal, mParamLocalNormalWorld);
    //addNormalRelatedCalculations(vsMain, mParamInTangent, mParamLocalTangentWorld, internalCounter);
    //addNormalRelatedCalculations(vsMain, mParamInBiNormal, mParamLocalBinormalWorld, internalCounter);

    return true;
}

//-----------------------------------------------------------------------
void DualQuaternionSkinning::addPositionCalculations(Function* vsMain)
{
    auto stage = vsMain->getStage(FFP_VS_TRANSFORM);

    if (mDoBoneCalculations == true)
    {
        if(mScalingShearingSupport)
        {
            //Construct a scaling and shearing matrix based on the blend weights
            for(int i = 0 ; i < getWeightCount() ; ++i)
            {
                //Assign the local param based on the current index of the scaling and shearing matrices
                stage.assign({In(mParamInScaleShearMatrices), At(mParamInIndices).mask(indexToMask(i)),
                              Out(mParamTempFloat3x4)});

                //Calculate the resultant scaling and shearing matrix based on the weights given
                addIndexedPositionWeight(vsMain, i, mParamTempFloat3x4, mParamTempFloat3x4, mParamBlendS);
            }

            //Transform the position based by the scaling and shearing matrix
            stage.callFunction(FFP_FUNC_TRANSFORM, mParamBlendS, mParamInPosition, mParamLocalBlendPosition);
        }
        else
        {
            //Assign the input position to the local blended position
            stage.assign(In(mParamInPosition).xyz(), mParamLocalBlendPosition);
        }

        //Set functions to calculate world position
        for(int i = 0 ; i < getWeightCount() ; ++i)
        {
            // Build the dual quaternion matrix
            stage.assign(
                {In(mParamInWorldMatrices), At(mParamInIndices).mask(indexToMask(i)), Out(mParamTempFloat2x4)});

            //Adjust the podalities of the dual quaternions
            if(mCorrectAntipodalityHandling)
            {
                adjustForCorrectAntipodality(vsMain, i, mParamTempFloat2x4);
            }

            //Calculate the resultant dual quaternion based on the weights given
            addIndexedPositionWeight(vsMain, i, mParamTempFloat2x4, mParamTempFloat2x4, mParamBlendDQ);
        }

        //Normalize the dual quaternion
        stage.callFunction(SGX_FUNC_NORMALIZE_DUAL_QUATERNION, mParamBlendDQ);

        //Calculate the blend position
        stage.callFunction(SGX_FUNC_CALCULATE_BLEND_POSITION, mParamLocalBlendPosition, mParamBlendDQ, mParamTempFloat4);

        //Update from object to projective space
        stage.callFunction(FFP_FUNC_TRANSFORM, mParamInViewProjMatrix, mParamTempFloat4, mParamOutPositionProj);
    }
    else
    {
        //update from object to projective space
        stage.callFunction(FFP_FUNC_TRANSFORM, mParamInWorldViewProjMatrix, mParamInPosition, mParamOutPositionProj);
    }
}

//-----------------------------------------------------------------------
void DualQuaternionSkinning::addNormalRelatedCalculations(Function* vsMain,
                                ParameterPtr& pNormalRelatedParam,
                                ParameterPtr& pNormalWorldRelatedParam)
{
    auto stage = vsMain->getStage(FFP_VS_TRANSFORM);

    if (mDoBoneCalculations == true)
    {
        if(mScalingShearingSupport)
        {
            //Calculate the adjoint transpose of the blended scaling and shearing matrix
            stage.callFunction(SGX_FUNC_ADJOINT_TRANSPOSE_MATRIX, mParamBlendS, mParamTempFloat3x3);
            //Transform the normal by the adjoint transpose of the blended scaling and shearing matrix
            stage.callFunction(FFP_FUNC_TRANSFORM, mParamTempFloat3x3, pNormalRelatedParam, pNormalRelatedParam);
            //Need to normalize again after transforming the normal
            stage.callFunction(FFP_FUNC_NORMALIZE, pNormalRelatedParam);
        }
        //Transform the normal according to the dual quaternion
        stage.callFunction(SGX_FUNC_CALCULATE_BLEND_NORMAL, pNormalRelatedParam, mParamBlendDQ, pNormalWorldRelatedParam);
        //update back the original position relative to the object
        stage.callFunction(FFP_FUNC_TRANSFORM, mParamInInvWorldMatrix, pNormalWorldRelatedParam, pNormalRelatedParam);
    }
    else
    {
        //update from object to world space
        stage.callFunction(FFP_FUNC_TRANSFORM, mParamInWorldMatrix, pNormalRelatedParam, pNormalWorldRelatedParam);
    }
}

//-----------------------------------------------------------------------
void DualQuaternionSkinning::adjustForCorrectAntipodality(Function* vsMain,
                                int index, const ParameterPtr& pTempWorldMatrix)
{
    auto stage = vsMain->getStage(FFP_VS_TRANSFORM);

    //Antipodality doesn't need to be adjusted for dq0 on itself (used as the basis of antipodality calculations)
    if(index > 0)
    {
        //This is the base dual quaternion dq0, which the antipodality calculations are based on
        stage.callFunction(SGX_FUNC_ANTIPODALITY_ADJUSTMENT, mParamInitialDQ, mParamTempFloat2x4, pTempWorldMatrix);
    }
    else if(index == 0)
    {
        //Set the first dual quaternion as the initial dq
        stage.assign(mParamTempFloat2x4, mParamInitialDQ);
    }
}

//-----------------------------------------------------------------------
void DualQuaternionSkinning::addIndexedPositionWeight(Function* vsMain, int index,
                                ParameterPtr& pWorldMatrix, ParameterPtr& pPositionTempParameter,
                                ParameterPtr& pPositionRelatedOutputParam)
{
    auto stage = vsMain->getStage(FFP_VS_TRANSFORM);

    //multiply position with world matrix and put into temporary param
    stage.mul(In(mParamInWeights).mask(indexToMask(index)), pWorldMatrix, pPositionTempParameter);

    //check if on first iteration
    if (index == 0)
    {
        //set the local param as the value of the world param
        stage.assign(pPositionTempParameter, pPositionRelatedOutputParam);
    }
    else
    {
        //add the local param as the value of the world param
        stage.add(pPositionTempParameter, pPositionRelatedOutputParam, pPositionRelatedOutputParam);
    }
}

}
}

#endif

<commit_msg>RTSS: DualQuaternionSkinning - fix interplay with projective texturing<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org

Copyright (c) 2000-2014 Torus Knot Software Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "OgreShaderPrecompiledHeaders.h"

#ifdef RTSHADER_SYSTEM_BUILD_EXT_SHADERS
#define HS_DATA_BIND_NAME "HS_SRS_DATA"

namespace Ogre {

namespace RTShader {

/************************************************************************/
/*                                                                      */
/************************************************************************/
DualQuaternionSkinning::DualQuaternionSkinning() : HardwareSkinningTechnique()
{
}

//-----------------------------------------------------------------------
bool DualQuaternionSkinning::resolveParameters(ProgramSet* programSet)
{
    Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
    Function* vsMain = vsProgram->getEntryPointFunction();

    //if needed mark this vertex program as hardware skinned
    if (mDoBoneCalculations == true)
    {
        vsProgram->setSkeletalAnimationIncluded(true);
    }

    //
    // get the parameters we need whether we are doing bone calculations or not
    //
    // Note: in order to be consistent we will always output position, normal,
    // tangent and binormal in both object and world space. And output position
    // in projective space to cover the responsibility of the transform stage

    //input param
    mParamInPosition = vsMain->resolveInputParameter(Parameter::SPC_POSITION_OBJECT_SPACE);

    if(mDoLightCalculations)
        mParamInNormal = vsMain->resolveInputParameter(Parameter::SPC_NORMAL_OBJECT_SPACE);
    //mParamInBiNormal = vsMain->resolveInputParameter(Parameter::SPS_BINORMAL, 0, Parameter::SPC_BINORMAL_OBJECT_SPACE, GCT_FLOAT3);
    //mParamInTangent = vsMain->resolveInputParameter(Parameter::SPS_TANGENT, 0, Parameter::SPC_TANGENT_OBJECT_SPACE, GCT_FLOAT3);

    //local param
    mParamLocalBlendPosition = vsMain->resolveLocalParameter("BlendedPosition", GCT_FLOAT3);
    mParamLocalNormalWorld = vsMain->resolveLocalParameter(Parameter::SPC_NORMAL_WORLD_SPACE);
    //mParamLocalTangentWorld = vsMain->resolveLocalParameter(Parameter::SPS_TANGENT, 0, Parameter::SPC_TANGENT_WORLD_SPACE, GCT_FLOAT3);
    //mParamLocalBinormalWorld = vsMain->resolveLocalParameter(Parameter::SPS_BINORMAL, 0, Parameter::SPC_BINORMAL_WORLD_SPACE, GCT_FLOAT3);

    //output param
    mParamOutPositionProj = vsMain->resolveOutputParameter(Parameter::SPC_POSITION_PROJECTIVE_SPACE);

    if (mDoBoneCalculations == true)
    {
        //input parameters
        mParamInIndices = vsMain->resolveInputParameter(Parameter::SPC_BLEND_INDICES);
        mParamInWeights = vsMain->resolveInputParameter(Parameter::SPC_BLEND_WEIGHTS);
        mParamInWorldMatrices = vsProgram->resolveParameter(GpuProgramParameters::ACT_WORLD_DUALQUATERNION_ARRAY_2x4, mBoneCount);
        mParamInInvWorldMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_INVERSE_WORLD_MATRIX);
        mParamInViewProjMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_VIEWPROJ_MATRIX);

        mParamTempWorldMatrix = vsMain->resolveLocalParameter("worldMatrix", GCT_MATRIX_2X4);
        mParamBlendDQ = vsMain->resolveLocalParameter("blendDQ", GCT_MATRIX_2X4);
        mParamInitialDQ = vsMain->resolveLocalParameter("initialDQ", GCT_MATRIX_2X4);

        if (ShaderGenerator::getSingleton().getTargetLanguage() == "hlsl")
        {
            //set hlsl shader to use row-major matrices instead of column-major.
            //it enables the use of auto-bound 3x4 matrices in generated hlsl shader.
            vsProgram->setUseColumnMajorMatrices(false);
        }

        if(mScalingShearingSupport)
        {
            mParamInScaleShearMatrices = vsProgram->resolveParameter(GpuProgramParameters::ACT_WORLD_SCALE_SHEAR_MATRIX_ARRAY_3x4, mBoneCount);
            mParamBlendS = vsMain->resolveLocalParameter("blendS", GCT_MATRIX_3X4);
            mParamTempFloat3x3 = vsMain->resolveLocalParameter("TempVal3x3", GCT_MATRIX_3X3);
            mParamTempFloat3x4 = vsMain->resolveLocalParameter("TempVal3x4", GCT_MATRIX_3X4);
        }

        mParamTempFloat2x4 = vsMain->resolveLocalParameter("TempVal2x4", GCT_MATRIX_2X4);
        mParamTempFloat4 = vsMain->resolveLocalParameter("TempVal4", GCT_FLOAT4);
        mParamTempFloat3 = vsMain->resolveLocalParameter("TempVal3", GCT_FLOAT3);
    }
    else
    {
        mParamInWorldMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_WORLD_MATRIX);
        mParamInWorldViewProjMatrix = vsProgram->resolveParameter(GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
    }
    return true;
}

//-----------------------------------------------------------------------
bool DualQuaternionSkinning::resolveDependencies(ProgramSet* programSet)
{
    Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
    vsProgram->addDependency(FFP_LIB_COMMON);
    vsProgram->addDependency(FFP_LIB_TRANSFORM);
    vsProgram->addDependency(SGX_LIB_DUAL_QUATERNION);

    return true;
}

//-----------------------------------------------------------------------
bool DualQuaternionSkinning::addFunctionInvocations(ProgramSet* programSet)
{
    Program* vsProgram = programSet->getCpuProgram(GPT_VERTEX_PROGRAM);
    Function* vsMain = vsProgram->getEntryPointFunction();

    //add functions to calculate position data in world, object and projective space
    addPositionCalculations(vsMain);

    //add functions to calculate normal and normal related data in world and object space
    if(mDoLightCalculations)
        addNormalRelatedCalculations(vsMain, mParamInNormal, mParamLocalNormalWorld);
    //addNormalRelatedCalculations(vsMain, mParamInTangent, mParamLocalTangentWorld, internalCounter);
    //addNormalRelatedCalculations(vsMain, mParamInBiNormal, mParamLocalBinormalWorld, internalCounter);

    return true;
}

//-----------------------------------------------------------------------
void DualQuaternionSkinning::addPositionCalculations(Function* vsMain)
{
    auto stage = vsMain->getStage(FFP_VS_TRANSFORM);

    if (mDoBoneCalculations == true)
    {
        if(mScalingShearingSupport)
        {
            //Construct a scaling and shearing matrix based on the blend weights
            for(int i = 0 ; i < getWeightCount() ; ++i)
            {
                //Assign the local param based on the current index of the scaling and shearing matrices
                stage.assign({In(mParamInScaleShearMatrices), At(mParamInIndices).mask(indexToMask(i)),
                              Out(mParamTempFloat3x4)});

                //Calculate the resultant scaling and shearing matrix based on the weights given
                addIndexedPositionWeight(vsMain, i, mParamTempFloat3x4, mParamTempFloat3x4, mParamBlendS);
            }

            //Transform the position based by the scaling and shearing matrix
            stage.callFunction(FFP_FUNC_TRANSFORM, mParamBlendS, mParamInPosition, mParamLocalBlendPosition);
        }
        else
        {
            //Assign the input position to the local blended position
            stage.assign(In(mParamInPosition).xyz(), mParamLocalBlendPosition);
        }

        //Set functions to calculate world position
        for(int i = 0 ; i < getWeightCount() ; ++i)
        {
            // Build the dual quaternion matrix
            stage.assign(
                {In(mParamInWorldMatrices), At(mParamInIndices).mask(indexToMask(i)), Out(mParamTempFloat2x4)});

            //Adjust the podalities of the dual quaternions
            if(mCorrectAntipodalityHandling)
            {
                adjustForCorrectAntipodality(vsMain, i, mParamTempFloat2x4);
            }

            //Calculate the resultant dual quaternion based on the weights given
            addIndexedPositionWeight(vsMain, i, mParamTempFloat2x4, mParamTempFloat2x4, mParamBlendDQ);
        }

        //Normalize the dual quaternion
        stage.callFunction(SGX_FUNC_NORMALIZE_DUAL_QUATERNION, mParamBlendDQ);

        //Calculate the blend position
        stage.callFunction(SGX_FUNC_CALCULATE_BLEND_POSITION, mParamLocalBlendPosition, mParamBlendDQ, mParamTempFloat4);

        //Update from object to projective space
        stage.callFunction(FFP_FUNC_TRANSFORM, mParamInViewProjMatrix, mParamTempFloat4, mParamOutPositionProj);

        //update back the original position relative to the object
        stage.callFunction(FFP_FUNC_TRANSFORM, mParamInInvWorldMatrix, mParamTempFloat4,
                           mParamInPosition);
    }
    else
    {
        //update from object to projective space
        stage.callFunction(FFP_FUNC_TRANSFORM, mParamInWorldViewProjMatrix, mParamInPosition, mParamOutPositionProj);
    }
}

//-----------------------------------------------------------------------
void DualQuaternionSkinning::addNormalRelatedCalculations(Function* vsMain,
                                ParameterPtr& pNormalRelatedParam,
                                ParameterPtr& pNormalWorldRelatedParam)
{
    auto stage = vsMain->getStage(FFP_VS_TRANSFORM);

    if (mDoBoneCalculations == true)
    {
        if(mScalingShearingSupport)
        {
            //Calculate the adjoint transpose of the blended scaling and shearing matrix
            stage.callFunction(SGX_FUNC_ADJOINT_TRANSPOSE_MATRIX, mParamBlendS, mParamTempFloat3x3);
            //Transform the normal by the adjoint transpose of the blended scaling and shearing matrix
            stage.callFunction(FFP_FUNC_TRANSFORM, mParamTempFloat3x3, pNormalRelatedParam, pNormalRelatedParam);
            //Need to normalize again after transforming the normal
            stage.callFunction(FFP_FUNC_NORMALIZE, pNormalRelatedParam);
        }
        //Transform the normal according to the dual quaternion
        stage.callFunction(SGX_FUNC_CALCULATE_BLEND_NORMAL, pNormalRelatedParam, mParamBlendDQ, pNormalWorldRelatedParam);
        //update back the original position relative to the object
        stage.callFunction(FFP_FUNC_TRANSFORM, mParamInInvWorldMatrix, pNormalWorldRelatedParam, pNormalRelatedParam);
    }
    else
    {
        //update from object to world space
        stage.callFunction(FFP_FUNC_TRANSFORM, mParamInWorldMatrix, pNormalRelatedParam, pNormalWorldRelatedParam);
    }
}

//-----------------------------------------------------------------------
void DualQuaternionSkinning::adjustForCorrectAntipodality(Function* vsMain,
                                int index, const ParameterPtr& pTempWorldMatrix)
{
    auto stage = vsMain->getStage(FFP_VS_TRANSFORM);

    //Antipodality doesn't need to be adjusted for dq0 on itself (used as the basis of antipodality calculations)
    if(index > 0)
    {
        //This is the base dual quaternion dq0, which the antipodality calculations are based on
        stage.callFunction(SGX_FUNC_ANTIPODALITY_ADJUSTMENT, mParamInitialDQ, mParamTempFloat2x4, pTempWorldMatrix);
    }
    else if(index == 0)
    {
        //Set the first dual quaternion as the initial dq
        stage.assign(mParamTempFloat2x4, mParamInitialDQ);
    }
}

//-----------------------------------------------------------------------
void DualQuaternionSkinning::addIndexedPositionWeight(Function* vsMain, int index,
                                ParameterPtr& pWorldMatrix, ParameterPtr& pPositionTempParameter,
                                ParameterPtr& pPositionRelatedOutputParam)
{
    auto stage = vsMain->getStage(FFP_VS_TRANSFORM);

    //multiply position with world matrix and put into temporary param
    stage.mul(In(mParamInWeights).mask(indexToMask(index)), pWorldMatrix, pPositionTempParameter);

    //check if on first iteration
    if (index == 0)
    {
        //set the local param as the value of the world param
        stage.assign(pPositionTempParameter, pPositionRelatedOutputParam);
    }
    else
    {
        //add the local param as the value of the world param
        stage.add(pPositionTempParameter, pPositionRelatedOutputParam, pPositionRelatedOutputParam);
    }
}

}
}

#endif

<|endoftext|>


<commit_before>//
//  AppleGCR.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 21/04/2018.
//  Copyright 2018 Thomas Harte. All rights reserved.
//

#ifndef AppleGCR_hpp
#define AppleGCR_hpp

#include <cstdint>
#include "../../../Disk/Track/PCMSegment.hpp"

namespace Storage {
namespace Encodings {
namespace AppleGCR {

/// Describes the standard three-byte prologue that begins a header on both the Macintosh and the Apple II from DOS 3.3.
constexpr uint8_t header_prologue[3] = {0xd5, 0xaa, 0x96};
/// Describes the standard three-byte prologue that begins a data section.
constexpr uint8_t data_prologue[3] = {0xd5, 0xaa, 0xad};
/// Describes the epilogue that ends both data sections and headers.
constexpr uint8_t epilogue[3] = {0xde, 0xaa, 0xeb};
/// Describes the standard three-byte prologue used by DOS 3.2 and earlier.
constexpr uint8_t five_and_three_header_prologue[3] = {0xd5, 0xaa, 0xb5};

namespace AppleII {

/*!
	Produces the data section of an Apple II-style six-and-two format sector;
	the segment returned will be 2,792 bits long, encoding the first 256 bytes
	from @c source.
*/
Storage::Disk::PCMSegment six_and_two_data(const uint8_t *source);

/*!
	Produces the Apple II-standard four-and-four per-sector header. This is the same
	for both the 13- and 16-sector formats, and is 112 bits long.
*/
Storage::Disk::PCMSegment header(uint8_t volume, uint8_t track, uint8_t sector);

}

namespace Macintosh {

struct SectorSpan {
	int start, length;
};

/*!
	@returns the span of sectors included on track @c track using the Macintosh's
	ordinary CLV variable-speed mechanish.
*/
SectorSpan sectors_in_track(int track);

/*!
	Produces the data section of a Macintosh-format sector;
	the segment returned will be 5680 bits long, encoding the first 524 bytes
	from @c source and including a record of the @c sector.
*/
Storage::Disk::PCMSegment data(uint8_t sector, const uint8_t *source);

/*!
	Produces the Mac-standard header. This is 88 bits long.
*/
Storage::Disk::PCMSegment header(uint8_t type, uint8_t track, uint8_t sector, bool side_two);

/// The on-disk type used for a 400kb floppy.
const uint8_t TypeMac400kb = 0x02;
/// The on-disk type used for a 800kb floppy.
const uint8_t TypeMac800kb = 0x22;

}

/*!
	Produces @c length sync six-and-two format sync bytes. The segment returned
	is @c 10*length bits long.
*/
Storage::Disk::PCMSegment six_and_two_sync(int length);

/*!
	Produces the data section of a five-and-three format sector; the segment returned
	will be 3,336 bits long, encoding the first 256 bytes from @c source.

	(TODO).
*/
Storage::Disk::PCMSegment five_and_three_data(const uint8_t *source);

/*!
	Produces @c length sync five-and-three format sync bytes. The segment returned
	is @c 9*length bits long.
*/
Storage::Disk::PCMSegment five_and_three_sync(int length);

}
}
}

#endif /* AppleGCR_hpp */
<commit_msg>Adds an informal guarantee.<commit_after>//
//  AppleGCR.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 21/04/2018.
//  Copyright 2018 Thomas Harte. All rights reserved.
//

#ifndef AppleGCR_hpp
#define AppleGCR_hpp

#include <cstdint>
#include "../../../Disk/Track/PCMSegment.hpp"

namespace Storage {
namespace Encodings {
namespace AppleGCR {

/// Describes the standard three-byte prologue that begins a header on both the Macintosh and the Apple II from DOS 3.3.
constexpr uint8_t header_prologue[3] = {0xd5, 0xaa, 0x96};
/// Describes the standard three-byte prologue that begins a data section.
constexpr uint8_t data_prologue[3] = {0xd5, 0xaa, 0xad};
/// Describes the epilogue that ends both data sections and headers.
constexpr uint8_t epilogue[3] = {0xde, 0xaa, 0xeb};
/// Describes the standard three-byte prologue used by DOS 3.2 and earlier.
constexpr uint8_t five_and_three_header_prologue[3] = {0xd5, 0xaa, 0xb5};

namespace AppleII {

/*!
	Produces the data section of an Apple II-style six-and-two format sector;
	the segment returned will be 2,792 bits long, encoding the first 256 bytes
	from @c source.
*/
Storage::Disk::PCMSegment six_and_two_data(const uint8_t *source);

/*!
	Produces the Apple II-standard four-and-four per-sector header. This is the same
	for both the 13- and 16-sector formats, and is 112 bits long.
*/
Storage::Disk::PCMSegment header(uint8_t volume, uint8_t track, uint8_t sector);

}

namespace Macintosh {

struct SectorSpan {
	int start, length;
};

/*!
	@returns the span of sectors included on track @c track using the Macintosh's
	ordinary CLV variable-speed mechanish. Guaranteed to be 12 or fewer.
*/
SectorSpan sectors_in_track(int track);

/*!
	Produces the data section of a Macintosh-format sector;
	the segment returned will be 5680 bits long, encoding the first 524 bytes
	from @c source and including a record of the @c sector.
*/
Storage::Disk::PCMSegment data(uint8_t sector, const uint8_t *source);

/*!
	Produces the Mac-standard header. This is 88 bits long.
*/
Storage::Disk::PCMSegment header(uint8_t type, uint8_t track, uint8_t sector, bool side_two);

/// The on-disk type used for a 400kb floppy.
const uint8_t TypeMac400kb = 0x02;
/// The on-disk type used for a 800kb floppy.
const uint8_t TypeMac800kb = 0x22;

}

/*!
	Produces @c length sync six-and-two format sync bytes. The segment returned
	is @c 10*length bits long.
*/
Storage::Disk::PCMSegment six_and_two_sync(int length);

/*!
	Produces the data section of a five-and-three format sector; the segment returned
	will be 3,336 bits long, encoding the first 256 bytes from @c source.

	(TODO).
*/
Storage::Disk::PCMSegment five_and_three_data(const uint8_t *source);

/*!
	Produces @c length sync five-and-three format sync bytes. The segment returned
	is @c 9*length bits long.
*/
Storage::Disk::PCMSegment five_and_three_sync(int length);

}
}
}

#endif /* AppleGCR_hpp */
<|endoftext|>


<commit_before>#include "proctor/si_wrapper.h"

#include <pcl/features/spin_image.h>

namespace pcl
{

  namespace proctor
  {

    void
    SIWrapper::compute(PointCloud<PointNormal>::Ptr cloud, PointCloud<PointNormal>::Ptr keypoints, pcl::PointCloud<Eigen::MatrixXf> &output)
    {
      SpinImageEstimation<PointNormal, PointNormal, Eigen::MatrixXf> si (8, 0.5, 10);
      si.setRadiusSearch(0.08);
      search::KdTree<PointNormal>::Ptr kdt (new search::KdTree<PointNormal>());
      si.setSearchMethod(kdt);

      si.setInputCloud(keypoints);
      //si.setSearchSurface(cloud);
      //si.setSearchSurfaceNormals(cloud);
      //si.setInputNormals(keypoints);
      //si.setSearchSurfaceWithNormals(cloud, cloud);
      //si.setInputWithNormals(keypoints, keypoints);
      si.computeEigen(output);
    }

  }

}

<commit_msg>Fix spin images.<commit_after>#include "proctor/si_wrapper.h"

#include <pcl/features/spin_image.h>

namespace pcl
{

  namespace proctor
  {

    void
    SIWrapper::compute(PointCloud<PointNormal>::Ptr cloud, PointCloud<PointNormal>::Ptr keypoints, pcl::PointCloud<Eigen::MatrixXf> &output)
    {
      SpinImageEstimation<PointNormal, PointNormal, Eigen::MatrixXf> si;
      search::KdTree<PointNormal>::Ptr kdt (new search::KdTree<PointNormal>());
      si.setSearchMethod(kdt);
      si.setRadiusSearch(0.08);

      si.setInputCloud(keypoints);
      si.setInputNormals(keypoints);
      si.setSearchSurface(cloud);
      si.computeEigen(output);
    }

  }

}

<|endoftext|>