00001 #ifndef __Y_RKDTREE_H
00002 #define __Y_RKDTREE_H
00003
00004 #include <yafray_config.h>
00005
00006 #include <algorithm>
00007
00008 #include <utilities/y_alloc.h>
00009 #include <core_api/bound.h>
00010 #include <core_api/object3d.h>
00011 #include <yafraycore/kdtree.h>
00012
00013
00014 __BEGIN_YAFRAY
00015
00016 extern int Kd_inodes, Kd_leaves, _emptyKd_leaves, Kd_prims, _clip, _bad_clip, _null_clip, _early_out;
00017
00018 class renderState_t;
00019
00020 #define PRIM_DAT_SIZE 32
00021
00022
00027 template<class T> class rkdTreeNode
00028 {
00029 public:
00030 void createLeaf(u_int32 *primIdx, int np, const T **prims, MemoryArena &arena)
00031 {
00032 primitives = 0;
00033 flags = np << 2;
00034 flags |= 3;
00035 if(np>1)
00036 {
00037 primitives = (T **)arena.Alloc(np * sizeof(T *));
00038 for(int i=0;i<np;i++) primitives[i] = (T *)prims[primIdx[i]];
00039 Kd_prims+=np;
00040 }
00041 else if(np==1)
00042 {
00043 onePrimitive = (T *)prims[primIdx[0]];
00044 Kd_prims++;
00045 }
00046 else _emptyKd_leaves++;
00047 Kd_leaves++;
00048 }
00049 void createInterior(int axis, PFLOAT d)
00050 { division = d; flags = (flags & ~3) | axis; Kd_inodes++; }
00051 PFLOAT SplitPos() const { return division; }
00052 int SplitAxis() const { return flags & 3; }
00053 int nPrimitives() const { return flags >> 2; }
00054 bool IsLeaf() const { return (flags & 3) == 3; }
00055 u_int32 getRightChild() const { return (flags >> 2); }
00056 void setRightChild(u_int32 i) { flags = (flags&3) | (i << 2); }
00057
00058 union
00059 {
00060 PFLOAT division;
00061 T** primitives;
00062 T* onePrimitive;
00063 };
00064 u_int32 flags;
00065 };
00066
00068 template<class T> struct rKdStack
00069 {
00070 const rkdTreeNode<T> *node;
00071 PFLOAT t;
00072 point3d_t pb;
00073 int prev;
00074 };
00075
00076
00080 template<class T> class YAFRAYCORE_EXPORT kdTree_t
00081 {
00082 public:
00083 kdTree_t(const T **v, int np, int depth=-1, int leafSize=2,
00084 float cost_ratio=0.35, float emptyBonus=0.33);
00085 bool Intersect(const ray_t &ray, PFLOAT dist, T **tr, PFLOAT &Z, void *udat) const;
00086
00087 bool IntersectS(const ray_t &ray, PFLOAT dist, T **tr) const;
00088 bool IntersectTS(renderState_t &state, const ray_t &ray, int maxDepth, PFLOAT dist, T **tr, color_t &filt) const;
00089
00090 bound_t getBound(){ return treeBound; }
00091 ~kdTree_t();
00092 private:
00093 void pigeonMinCost(u_int32 nPrims, bound_t &nodeBound, u_int32 *primIdx, splitCost_t &split);
00094 void minimalCost(u_int32 nPrims, bound_t &nodeBound, u_int32 *primIdx,
00095 const bound_t *allBounds, boundEdge *edges[3], splitCost_t &split);
00096 int buildTree(u_int32 nPrims, bound_t &nodeBound, u_int32 *primNums,
00097 u_int32 *leftPrims, u_int32 *rightPrims, boundEdge *edges[3],
00098 u_int32 rightMemSize, int depth, int badRefines );
00099
00100 float costRatio;
00101 float eBonus;
00102 u_int32 nextFreeNode, allocatedNodesCount, totalPrims;
00103 int maxDepth;
00104 unsigned int maxLeafSize;
00105 bound_t treeBound;
00106 MemoryArena primsArena;
00107 rkdTreeNode<T> *nodes;
00108
00109
00110 const T **prims;
00111 bound_t *allBounds;
00112 int *clip;
00113 char *cdata;
00114
00115
00116 int depthLimitReached, NumBadSplits;
00117 };
00118
00119
00120 __END_YAFRAY
00121 #endif //__Y_RKDTREE_H