// ================================================================ // $Id$ // **************************************************************** // // Initial coding by /** @author Jiri Bittner */ #ifndef __VSSTREE_H__ #define __VSSTREE_H__ // Standard headers #include #include #include #include // User headers #include "VssRay.h" #include "AxisAlignedBox3.h" #include "Statistics.h" #include "Ray.h" namespace GtpVisibilityPreprocessor { #define USE_KDNODE_VECTORS 1 #define _RSS_STATISTICS #define _RSS_TRAVERSAL_STATISTICS // -------------------------------------------------------------- // Static statistics for kd-tree search // -------------------------------------------------------------- class VssStatistics : public StatisticsBase { public: // total number of nodes int nodes; // number of splits along each of the axes int splits[7]; // totals number of rays int rays; // initial size of the pvs int initialPvsSize; // total number of query domains int queryDomains; // total number of ray references int rayRefs; // max depth nodes int maxDepthNodes; // max depth nodes int minPvsNodes; int minRaysNodes; // max ray contribution nodes int maxRayContribNodes; // max depth nodes int minSizeNodes; int maxCostRatioNodes; // max number of rays per node int maxRayRefs; // number of dynamically added ray refs int addedRayRefs; // number of dynamically removed ray refs int removedRayRefs; // Constructor VssStatistics() { Reset(); } int Nodes() const {return nodes;} int Interior() const { return nodes/2; } int Leaves() const { return (nodes/2) + 1; } void Reset() { nodes = 0; for (int i=0; i<7; i++) splits[i] = 0; rays = queryDomains = 0; rayRefs = 0; maxDepthNodes = 0; minPvsNodes = 0; minRaysNodes = 0; maxRayRefs = 0; addedRayRefs = removedRayRefs = 0; initialPvsSize = 0; maxRayContribNodes = 0; minSizeNodes = 0; maxCostRatioNodes = 0; } void Print(ostream &app) const; friend ostream &operator<<(ostream &s, const VssStatistics &stat) { stat.Print(s); return s; } }; class VssTreeInterior; // -------------------------------------------------------------- // KD-tree node - abstract class // -------------------------------------------------------------- class VssTreeNode { public: #define USE_FIXEDPOINT_T 0 struct RayInfo { // pointer to the actual ray VssRay *mRay; // endpoints - do we need them? #if USE_FIXEDPOINT_T short mMinT, mMaxT; #else float mMinT, mMaxT; #endif RayInfo():mRay(NULL) {} RayInfo(VssRay *r):mRay(r), mMinT(0), #if USE_FIXEDPOINT_T #define FIXEDPOINT_ONE 0x7FFE // mMaxT(0xFFFF) mMaxT(FIXEDPOINT_ONE) #else mMaxT(1.0f) #endif {} RayInfo(VssRay *r, const float _min, const float _max ):mRay(r) { SetMinT(_min); SetMaxT(_max); } RayInfo(VssRay *r, const short _min, const float _max ):mRay(r), mMinT(_min) { SetMaxT(_max); } RayInfo(VssRay *r, const float _min, const short _max ):mRay(r), mMaxT(_max) { SetMinT(_min); } enum { SOURCE_RAY = 0, TERMINATION_RAY, PASSING_RAY, CONTAINED_RAY }; int GetRayClass() const { bool startsBefore = GetMinT() > 0.0f; bool terminatesAfter = GetMaxT() < 1.0f; if (startsBefore && terminatesAfter) return PASSING_RAY; if (!startsBefore && !terminatesAfter) return CONTAINED_RAY; if (!startsBefore) return SOURCE_RAY; return TERMINATION_RAY; } friend bool operator<(const RayInfo &a, const RayInfo &b) { return a.mRay < b.mRay; } float ExtrapOrigin(const int axis) const { return mRay->GetOrigin(axis) + GetMinT()*mRay->GetDir(axis); } float ExtrapTermination(const int axis) const { return mRay->GetOrigin(axis) + GetMaxT()*mRay->GetDir(axis); } Vector3 Extrap(const float t) const { return mRay->Extrap(t); } #if USE_FIXEDPOINT_T float GetMinT () const { return mMinT/(float)(FIXEDPOINT_ONE); } float GetMaxT () const { return mMaxT/(float)(FIXEDPOINT_ONE); } void SetMinT (const float t) { mMinT = (short) (t*(float)(FIXEDPOINT_ONE)); } void SetMaxT (const float t) { mMaxT = (short) (t*(float)(FIXEDPOINT_ONE)); mMaxT++; // if (mMaxT!=0xFFFF) // mMaxT++; } #else float GetMinT () const { return mMinT; } float GetMaxT () const { return mMaxT; } void SetMinT (const float t) { mMinT = t; } void SetMaxT (const float t) { mMaxT = t; } #endif int ComputeRayIntersection(const int axis, const float position, float &t ) const { #if 1 // intersect the ray with the plane float denom = mRay->GetDir(axis); if (fabs(denom) < 1e-20) //if (denom == 0.0f) return (mRay->GetOrigin(axis) > position) ? 1 : -1; t = (position - mRay->GetOrigin(axis))/denom; if (t < GetMinT()) return (denom > 0) ? 1 : -1; if (t > GetMaxT()) return (denom > 0) ? -1 : 1; return 0; #else // subbdivision based only on the origin t = 0; float rpos = mRay->GetOrigin(axis); return (rpos < position) ? -1 : 1; #endif } }; void GetSampleData(const bool isTerminaton, Vector3 &pt, Intersectable **obj, KdNode **node) const; typedef vector RayInfoContainer; enum { EInterior, ELeaf }; ///////////////////////////////// // The actual data goes here // link to the parent VssTreeInterior *parent; enum {SPLIT_X=0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ}; // splitting axis char axis; // depth unsigned char depth; // short depth; // ///////////////////////////////// inline VssTreeNode(VssTreeInterior *p); virtual ~VssTreeNode() {}; virtual int Type() const = 0; bool IsLeaf() const { return axis == -1; } virtual void Print(ostream &s) const = 0; virtual int GetAccessTime() { return 0x7FFFFFF; } }; // -------------------------------------------------------------- // KD-tree node - interior node // -------------------------------------------------------------- class VssTreeInterior : public VssTreeNode { public: // plane in local modelling coordinates float position; // pointers to children VssTreeNode *back, *front; // the bbox of the node AxisAlignedBox3 bbox; // the bbox of the node AxisAlignedBox3 dirBBox; // data for caching long accesses; long lastAccessTime; VssTreeInterior(VssTreeInterior *p):VssTreeNode(p), back(NULL), front(NULL), accesses(0), lastAccessTime(-1) { } virtual int GetAccessTime() { return lastAccessTime; } void SetupChildLinks(VssTreeNode *b, VssTreeNode *f) { back = b; front = f; b->parent = f->parent = this; } void ReplaceChildLink(VssTreeNode *oldChild, VssTreeNode *newChild) { if (back == oldChild) back = newChild; else front = newChild; } virtual int Type() const { return EInterior; } virtual ~VssTreeInterior() { if (back) delete back; if (front) delete front; } virtual void Print(ostream &s) const { if (axis == 0) s<<"x "; else if (axis == 1) s<<"y "; else s<<"z "; s<Print(s); front->Print(s); } int ComputeRayIntersection(const RayInfo &rayData, float &t ) { return rayData.ComputeRayIntersection(axis, position, t); } }; // -------------------------------------------------------------- // KD-tree node - leaf node // -------------------------------------------------------------- class VssTreeLeaf : public VssTreeNode { private: int mPvsSize; public: static int mailID; int mailbox; RayInfoContainer rays; int mPassingRays; bool mValidPvs; float mEntropyImportance; VssTreeLeaf(VssTreeInterior *p, const int nRays ):VssTreeNode(p), rays(), mPvsSize(0), mPassingRays(0), mValidPvs(false) { rays.reserve(nRays); } virtual ~VssTreeLeaf() { } virtual int Type() const { return ELeaf; } virtual void Print(ostream &s) const { s<