//////////////////////////////////////////////////////////////////////////////
//
//    Author	    : Gokhan Kisacikoglu
//    Date		: Wed Nov 21 11:43:47 PST 2001
//    File		: SFScalarFieldBlend.cpp
//    Description : Header file defining the SFScalarFieldBlend class
//
//////////////////////////////////////////////////////////////////////////////

#include <iostream.h>

#include "SFScalarFieldBlend.h"

//////////////////////////////////////////////////////////////////////////////
//
// SFScalarFieldBlend class
//
//////////////////////////////////////////////////////////////////////////////

// Inventor stuff
SO_ENGINE_SOURCE(SFScalarFieldBlend);

// Inventor stuff
void
SFScalarFieldBlend::initClass ()
{
  SO_ENGINE_INIT_CLASS(SFScalarFieldBlend, SoEngine, "Engine");
}

//////////////////////////////////////////////////////////////////////////////
//
//    Description:
//	Default constructor initializes all class fields
//
//////////////////////////////////////////////////////////////////////////////
SFScalarFieldBlend::SFScalarFieldBlend ()
{
  SO_ENGINE_CONSTRUCTOR(SFScalarFieldBlend);

  int dims[3] = {0};
  SO_ENGINE_ADD_INPUT(input1,	         (dims, 0, false));
  SO_ENGINE_ADD_INPUT(input2,	         (dims, 0, false));
  SO_ENGINE_ADD_INPUT(blendValue,		    (0.0));
    
  SO_ENGINE_ADD_OUTPUT(output,            SFScalarField);
}

SFScalarFieldBlend::~SFScalarFieldBlend ()
{

}

//////////////////////////////////////////////////////////////////////////////
//
//    Description:
//	Whenever the data field changes set the flag to recompute the
//	gradients.
//
//////////////////////////////////////////////////////////////////////////////
void
SFScalarFieldBlend::inputChanged (SoField *which)
{
}

//////////////////////////////////////////////////////////////////////////////
//
//    Description:
//	Called by Inventor each time an output has been called and an input has
//	been modified.    The points and the indexes will be computed here.
//
//////////////////////////////////////////////////////////////////////////////
void
SFScalarFieldBlend::evaluate ()
{
  // the blending amounts
  float blend = blendValue.getValue();
    
    // the input data 
    //	
  struct voxelData
  {
    int dims[3];
    //	SbVec3f min, max, voxel;
    float	*values;
  };
    
  voxelData data1;
  voxelData data2;
    
  data1.values = input1.getValue(data1.dims);
  data2.values = input2.getValue(data2.dims);
    
  // simple checks: we do not blend the data dimensions or boundaries.
  if ( blend == 0.0f || 
       data1.dims[0] != data2.dims[0] || 
       data1.dims[1] != data2.dims[1] || 
       data1.dims[2] != data2.dims[2])
    //data1.min != data2.min || 
    //data1.max != data2.max || 
    //data1.voxel != data2.voxel )
    {
      // sets the first data as emergency output
      // 
      // SFScalarField output
      SO_ENGINE_OUTPUT(output, SFScalarField,
		       setValue(data1.dims, data1.values, false));
      // Don't forget to set the bounds
      //SO_ENGINE_OUTPUT(output, SFScalarField,
      //	       setBounds(data1.min, data1.max));
	
      return;
    }
    
  // the output data
  //	
  int numPoints = data1.dims[0] * data1.dims[1] * data1.dims[2];

  blended.setSize(data1.dims);
  float *values = blended.getDataPtr();
    
  float blendminus = 1.0f - blend;
  for ( int i = numPoints; i > 0; -- i, ++ data1.values, ++ data2.values, ++ values )
    {
      *values = (*data1.values) * blendminus + (*data2.values) * blend;
    }

  SO_ENGINE_OUTPUT(output, SFScalarField,
		   setValue(data1.dims, blended.getDataPtr(), false));    
  // Don't forget to set the bounds
  //SO_ENGINE_OUTPUT(output, SFScalarField,
  //	   setBounds(data1.min, data1.max));
}
