// -*- C++ -*- #ifndef RIRADOBJECT_H #define RIRADOBJECT_H /* Copyright 1996 * Tue Jun 17 09:36:10 1997 Brian Smits (bes@phoenix.cs.utah.edu) * * RiRadObject.H * * * * $Id: RiRadObject.H,v 1.7 1998/06/22 17:36:47 bes Exp $ * */ #ifndef RICOMMON_H #include #endif #ifndef RIMATERIAL_H #include #endif #include class RiRadObject; /*************************************************************** CLASS RiRadRegion Encapsulates the notion of a sample on a RiRadObject. DESCRIPTION This class represents a sample on an RiRadObject. The sample consists of all data needed by an RiMaterial (such as position, area, normal, UV's) as well as a pointer to a RiRadObject. The RiRadObject pointer is the particular RiRadObject that the sample lives on. This may not be the RiRadObject that was queried to get the sample in the first place. If a higher level cluster is queried, the result may be a primitive object. ****************************************************************/ class RiRadRegion : public RiMaterialRegion { public: // GROUP: Constructors and assignment //// Default Constructor RiRadRegion(); // GROUP: Accessors //// Note that the object may not be the object used in the // original call. The original may have been a composite. RiRadObject *GetRadObject() const; //// Set the RiRadObject that the sample live on. void SetRadObject(RiRadObject *obj); private: RiRadObject *obj; }; class RiTransferData; class RiRefine; /*************************************************************** CLASS RiRadLink DESCRIPTION ****************************************************************/ class RiRadLink { public: //// Destructor virtual ~RiRadLink() {} // GROUP: Members //// gather the energy down this link virtual RiSpectrum Gather() = 0; //// Initialize data for use by RiRefine virtual void GetRefine(RiRefine &data, RiRadObject *rec) = 0; //// Get the Source object for this link virtual RiRadObject *GetSrc() = 0; }; /*************************************************************** CLASS RiRadData Holds all algorithm specific radiosity, emission, link, and error data. DESCRIPTION This is where things like lists of links, estimates of radiance or irradiance, and all solution data goes. This makes it simpler to change algorithms and add fields, because it can all be done here, instead of in each object. ****************************************************************/ class RiRadData { public: // GROUP: Constructors and assignment //// Default Constructor RiRadData(); //// RiRadData(const RiSpectrum &rad); //// RiRadData(const RiSpectrum &rad, const RiSpectrum &emit); // GROUP: Accessors //// Average in units of Radiance over object RiSpectrum GetEmission() const; //// Set average Emission void SetEmission(const RiSpectrum &emit); //// Average over object RiSpectrum GetRadiance() const; //// Set average radiance void SetRadiance(const RiSpectrum &rad); //// Average over object RiMaterial *GetMaterial() const; //// Set average radiance void SetMaterial(RiMaterial *mat); //// Initialize the data based on parent's data and areas void InitializeFrom(RiRadData *data, RiReal myArea, RiReal parentsArea); //// Give access to the links RWTValOrderedVector &GetLinks(); private: RiSpectrum rad; RiSpectrum emit; RiMaterial *mat; RWTValOrderedVector links; }; /*************************************************************** CLASS RiTransferData Encapsulate the data representing a transfer. DESCRIPTION This class eliminates the messy problem of how to encapsulate objects that only compute form factors and objects that only compute energy transfered (sky object). All error and data is stored here. This makes it easier to change algorithms without changing quadrature strategies, as basic operation needed to do quadrature on this data are implemented in the class, and can be changed to compute things differently. ****************************************************************/ class RiTransferData { public: // GROUP: Constructors and assignment //// Default Constructor RiTransferData(); ////Copy Constructor RiTransferData(const RiTransferData &); //// Assignment RiTransferData &operator=(const RiTransferData &); // GROUP: Accessors //// Set energy data void SetIrradiance(const RiSpectrum &energy, RiReal energyError); //// Set form factor data void SetFormFactor(RiReal ff, RiReal ffError); //// Set visibility data void SetVisibility(RiReal vis, RiReal visError); //// Get energy data void GetIrradiance(RiSpectrum &energy, RiReal &energyError) const; //// Get form factor data void GetFormFactor(RiReal &ff, RiReal &ffError) const; //// Get visibility data void GetVisibility(RiReal &vis, RiReal &visError) const; //// Get the estimated occluded irradiance RiSpectrum GetOccludedIrradiance() const; //// Get the estimated occluded form factor RiReal GetOccludedFormFactor() const; // GROUP: Members //// accumulate the total (handle errors appropriately) void operator+=(const RiTransferData &); //// scale results (handle errors appropriately) void operator*=(RiReal rhs); //// reset everything to zero void Clear(); //// does this hold energy? bool IsEnergy(); private: //// Hold the type of the data (makes things more efficient and safe?) enum Type {undefined, hasEnergy, hasFormFactor}; Type type; RiSpectrum energy; RiReal energyError; RiReal ff; RiReal ffError; RiReal vis; RiReal visError; }; /*************************************************************** CLASS RiConvexHull Represents a general convex hull for use by the Rad system for culling objects DESCRIPTION Abstract away the notion of the region of space and RiRadObject occupies. Allows any object to do visibility checks on any other object without knowing what the other object is. IMPLEMENTATION Currently this is implement with a maximum number of points of 8. After 8, the hull is represented as a bounding box of the points. ****************************************************************/ class RiConvexHull { public: // GROUP: Constructors and assignment //// Default Constructor RiConvexHull(); // GROUP: Accessors //// Add a point to the hull. The resulting hull will contain all previous // points, even if they aren't stored explicitly. void AddPoint(const RiVector3 &pnt); //// Get a point defining the hull RiVector3 GetPoint(int i) const; //// Get the number of points defining the hull (<= number added) int GetNumPoints() const; private: RiVector3 pnts[8]; int numPoints; bool isBox; }; /* class RiProjectedAreaSphere { AddDirection(const RiUnitVector3 &dir, RiFloat weight); RiReal GetProjectedArea(const RiVector3 &dir); }; */ /*************************************************************** CLASS RiRadObject Abstraction of all operations needed for an object to participate in a radiosity simulation. DESCRIPTION All operations needed for an object to participate in a radiosity simulation are included here. This task was made simpler by three other classes. RiRadRegion hides the notion of a sample point on a RiRadObject. RiTransferData hides the data needed to describe a transfer, either energy or form factors. RiRadData hides the energy and link values and temporaries that may be needed by the simulation. ****************************************************************/ class RiRadObject { public: //// Sets parent to NULL RiRadObject(); //// Empty virtual destructor virtual ~RiRadObject(){} // GROUP: Members //// Fills in the data in sample, and returns the Area Weight // for the sample. This is the probability density of this // point being chosen (1 over the area of the object for uniform sampling. virtual RiReal GetSample(RiRadRegion &sample, const RiVector2 &uv) = 0; //// Fills in the data in sample, and returns the Form Factor weight // for the sample to the interestedSample. interestedSample is used to // direct the object so that it will hopefully pick a point visible to // the intersted point, reducing variance. Form Factor weight is // FFdi,dx / p(x) where p(x) is often the return value from GetSample virtual RiReal GetFormFactorSample(RiRadRegion &sample, const RiMaterialRegion &interestedSample, const RiVector2 &uv); //// Compute transfer data for links and lighting. Should eventually // include visibility, but currently it does not. virtual void ComputeTransfer(const RiMaterialRegion &sample, RiTransferData &data) = 0; //// Get the Rad Data from the object virtual RiRadData *GetRadData() = 0; //// Get a convex hull containing the object virtual RiConvexHull GetConvexHull() = 0; //// Can the object see the convex hull. Note that this operation ONLY // involves the object and the hull, not the environment. This is // the equivalent of back face culling. virtual bool IsVisible(const RiConvexHull &hull) = 0; // GROUP: Structural //// Determine the number of children this object has. (0 if no // subdivision has been done virtual int GetNumChildren() = 0; //// Get the ith child (i MUST be less than GetNumChildren) virtual RiRadObject *GetChild(int i) = 0; //// Subdivide if possible. If already subdivided, do nothing. Return // true if subdividable. virtual bool Subdivide() = 0; //// Compute the surface area (or a good estimate of it) of the object virtual RiReal GetArea() = 0; //// find the leaf associated with this sample (If no leaf, return NULL) virtual RiRadObject *GetRadObject(const RiMaterialRegion &sample); //// void SetParent(RiRadObject *obj); //// RiRadObject *GetParent(); private: RiRadObject *parent; }; /*************************************************************** CLASS RiRadHierarchyBuilder Build a ray accelerator from a bunch of ray objects DESCRIPTION PATTERN Builder Iterator (sort of. no Next, no GetCurrent, build does the equivalent of GetCurrent; Next();) WARNINGS The RiRadObject 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 RiRadHierarchyBuilder { public: //// Destructor virtual ~RiRadHierarchyBuilder() {}; //// Add an object to the future accelerator virtual void AddObject(RiRadObject *) = 0; //// Build the RiRadObject and return it. // Each call to Build will build and return the next object. virtual RiRadObject *Build() = 0; //// Some situations result in a RiRadObjectBuilder // 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; }; // Should we assume source to point transfer is accurate (for ff and vis?) It's cleaner and probably // reasonable, as estimating those errors would be difficult and perhaps not even useful. #endif /* RIRADOBJECT_H */