/* -*-c++-*- */
/**
 * OsgAL - OpenSceneGraph Audio Library
 * Copyright (C) 2004 VRlab, Ume University
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 */

#ifndef osgAL_OccludeCallback_
#define osgAL_OccludeCallback_ 1

#include <iostream>
#include <osg/Referenced>
#include "osgAL/Export"
#include <osg/Node>
#include <osg/Matrix>
#include <osg/Timer>

namespace osgAL {

class SoundNode;
class SoundState;


/// Class to calculate occlusion between the listener and the soundsource
/*!
  OccludeCallback is executed from a SoundNode during traversal of the scene containing the soundnode.
  By analyzing if the sight is free by shooting a ray from the listener towards the soundnode, 
  a damping factor is applied to the gain of the soundstate for the current sound node.
  
  Currently only one ray is shot from the center of the listener to the center of the soundsource, instead
  of one per ear.
  
  The operator() method is executed both when the source is occluded as well as it is not.
  operator() implements the actually occlusion functionality.
  
  The default one, interpolates the damping over a short timeperiod trying to avoid clicks...
  
*/
class OSGAL_EXPORT OccludeCallback : public osg::Object {
public:

  /*!
	Constructor.
	\param root - The intersection ray will be shot at root:s all childrens.
  */
  OccludeCallback(osg::Node *root);

  /*!
	Constructor without args.
  */
  OccludeCallback();
  
  // Implementation of virtual functions of osg::Object
  virtual osg::Object* cloneType() const { return new OccludeCallback(); }
  virtual osg::Object* clone(const osg::CopyOp& copyop) const {
	  return new OccludeCallback(*this); 
  }
  virtual const char* libraryName() const { return "osgAL"; }
  virtual const char* className() const { return "OccludeCallback"; }
    
  /// Returns the specified distance between the ears
  float getEarDistance() const { return m_ear_distance; }
  
  /// If the ray hit an object outstide this distance from the sound node, it is culled
  void setNearThreshold(float t) { m_near_threshold = t; }
  
  ///
  float getNearThreshold() const { return m_near_threshold; }
  
  /// Set the node that will occlude the sound
  void setOccludingNode(osg::Node *root) {
	  m_root = root;
  }
  
  /// Get the node that will occlude the sound
  osg::Node * getOccludingNode() {
	  return m_root.get();
  }

  /// Get in const the node that will occlude the sound
  const osg::Node * getOccludingNode() const {
	  return m_root.get();
  }     
  
protected:
	virtual void operator()(double distance, osg::Node *occluder, bool left_occluded, bool right_occluded);

  SoundNode *getSoundNode() { return m_sound_node; }
    
private:
	friend class SoundNode;
	
	/*! Executed from SoundNode::traverse.
	\param listener_matrix - contains the transformation matrix for the listener.
	\param sound_pos - Position of the current sound node
	\param node - The current sound node.
	*/
	void apply(const osg::Matrix& listener_matrix, const osg::Vec3& sound_pos, osgAL::SoundNode *node);
  
	// The node from which the intersect is performed
	osg::ref_ptr<osg::Node> m_root;
	SoundNode *m_sound_node;
	float m_ear_distance;
	float m_near_threshold;
	
	//was the sound node occluded last frame?
	bool m_was_occluded;
	const double m_delay;	

	osg::Timer_t m_start_tick;


};

} // Namespace osgAL

#endif

