// -*- C++ -*-
#ifndef RIRAYOBJECT_H
#define RIRAYOBJECT_H
/* Copyright 1996 
 * Thu Mar 27 11:53:04 1997  Brian Edward Smits  (bes@burn.cs.utah.edu)
 * 
 * RiRayObject.H
 * 
 *	
 * 
 * $Id: RiRayObject.H,v 1.7 1999/06/10 20:11:41 bes Exp $ 
 * 
 */
#ifndef RICOMMON_H
#include <RiCommon.H>
#endif

#ifndef RIINTERVAL_H
#include <RiInterval.H>
#endif

#ifndef RIRAY3_H
#include <RiRay3.H>
#endif

#ifndef RIMATERIAL_H
#include <RiMaterial.H>
#endif

#ifndef RIAFFINETMATRIX3_H
#include <RiAffineTMatrix3.H>
#endif


class RiRayObject;
class RiLightObject;
/***************************************************************
CLASS
    RiRayHit
     Data needed to shade an intersection point

DESCRIPTION
     <Detailed description with any warnings>

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

class RiRayHit : public RiMaterialRegion {
  public:
				// GROUP: Constructors and assignment
				//// Default Constructor
    RiRayHit();
				// GROUP: Accessors
				////
    void	  SetMaterial(RiMaterial *m);
				////
    RiMaterial   *GetMaterial();
				////
    void	  SetObject(RiRayObject *o);
				////
    RiRayObject  *GetObject();
				////
    void	  SetTanConeAngle(RiReal t);
				////
    RiReal	  GetTanConeAngle();
  private:
    RiMaterial   *mat;
    RiRayObject  *obj;
    RiReal	  tanRayConeAngle;
};


class RiRayObjectVisitor;

/***************************************************************
CLASS
    RiRayObject
     Describes Functionality for all objects that are to be ray traced

DESCRIPTION
     This is a Mixin class. It contains no data, only functionality
     It is abstract.  All objects to be ray traced must inherit from
     RiRayObject.  In general, RiRayObject can be querried to create
     an RiBBox and can be intersected by an RiRay.  The intersection
     results in an RiRayHit.  All of these functions are const.  If the
     internals change (evaluation of procedural geometry), use that
     volitile construct.

IMPLEMENTATION DETAILS:
     The Intersect routine must set data in the hit and in the ray.
     The fields that must be set by the object are Object, Material,
     Normal, and UV's.  The ray must have it's max distance set to
     the intersection t value.

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

class RiRayObject {
  public:
    //// Destructor
    virtual ~RiRayObject() {}
				// GROUP: Members
				//// General interface for acceleration querries such
				// as bounding boxes and spheres.
    virtual RiInterval  GetMinMax(const RiUnitVector3 &) const = 0;
				//// Does the ray hit the object.  Nothing more.
    virtual bool	Shadow(RiRay3 &) const = 0;
				//// Compute an intersection and return it and any other
				//   data in the RiRayHit structure.  The T value for the ray
				//   is set correctly based on the intersection point.
    virtual bool	Intersect(RiRay3 &, RiRayHit &) = 0;
				//// Accept a visitor to perform (structure preserving)
				// actions on the hierarchy
    virtual void	Accept(RiRayObjectVisitor &visitor) = 0;
				//// Build a RiLightObject if possible, otherwise return NULL;
    virtual RiLightObject *BuildLightObject(const RiAffineTMatrix3 &mat);
				//// Estimated probability of hitting a primitive given that
				//   a ray hits this object's bounding box.
    virtual RiReal 	ConditionalHit() const;
};




/***************************************************************
CLASS
    RiRayAcceleratorBuilder
     Build a ray accelerator from a bunch of ray objects

DESCRIPTION
     <Detailed description with any warnings>

PATTERN
     Builder
     Iterator (sort of.  no Next, no GetCurrent, build does the equivalent of GetCurrent; Next();)
     
WARNINGS
     The RiRayObject returned from the builder is orphaned by the
     builder.  The client is responsible for deleting the object.
     Each call to Build will build the next object, returning NULL if
     no next object.

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

class RiRayAcceleratorBuilder {
  public:
				//// Destructor
    virtual ~RiRayAcceleratorBuilder() {};
				//// Add an object to the future accelerator
    virtual void 	 AddObject(RiRayObject *) = 0;
				//// Build the RiRayObject and return it.
				// Each call to Build will build and return the next object.
    virtual RiRayObject *Build() = 0;
				//// Some situations result in a RiRayObjectBuilder
				// building more than a single object.  As long as IsDone
				// returns false, there are more objects that need to be built
    virtual bool	 IsDone() = 0;
};



#endif /* RIRAYOBJECT_H */


