00001 #ifndef __Y_KDTREE_H
00002 #define __Y_KDTREE_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/meshtypes.h>
00012
00013 __BEGIN_YAFRAY
00014
00015 extern int Kd_inodes, Kd_leaves, _emptyKd_leaves, Kd_prims;
00016
00017 class renderState_t;
00018
00019 #define PRIM_DAT_SIZE 32
00020
00021
00026 class kdTreeNode
00027 {
00028 public:
00029 void createLeaf(u_int32 *primIdx, int np, const triangle_t **prims, MemoryArena &arena)
00030 {
00031 primitives = 0;
00032 flags = np << 2;
00033 flags |= 3;
00034 if(np>1)
00035 {
00036 primitives = (triangle_t **)arena.Alloc(np * sizeof(triangle_t *));
00037 for(int i=0;i<np;i++) primitives[i] = (triangle_t *)prims[primIdx[i]];
00038 Kd_prims+=np;
00039 }
00040 else if(np==1)
00041 {
00042 onePrimitive = (triangle_t *)prims[primIdx[0]];
00043 Kd_prims++;
00044 }
00045 else _emptyKd_leaves++;
00046 Kd_leaves++;
00047 }
00048 void createInterior(int axis, PFLOAT d)
00049 { division = d; flags = (flags & ~3) | axis; Kd_inodes++; }
00050 PFLOAT SplitPos() const { return division; }
00051 int SplitAxis() const { return flags & 3; }
00052 int nPrimitives() const { return flags >> 2; }
00053 bool IsLeaf() const { return (flags & 3) == 3; }
00054 u_int32 getRightChild() const { return (flags >> 2); }
00055 void setRightChild(u_int32 i) { flags = (flags&3) | (i << 2); }
00056
00057 union
00058 {
00059 PFLOAT division;
00060 triangle_t** primitives;
00061 triangle_t* onePrimitive;
00062 };
00063 u_int32 flags;
00064 };
00065
00069 class boundEdge {
00070 public:
00071 boundEdge(){};
00072 boundEdge(PFLOAT position, int primitive, int bound_end):
00073 pos(position), primNum(primitive), end(bound_end) {};
00074 bool operator<(const boundEdge &e) const {
00075 if (pos == e.pos)
00076 return (int)end > (int)e.end;
00077 else return pos < e.pos;
00078 }
00079 PFLOAT pos;
00080 int primNum;
00081 int end;
00082 };
00083
00085 struct KdStack
00086 {
00087 const kdTreeNode *node;
00088 PFLOAT t;
00089 point3d_t pb;
00090 int prev;
00091 };
00092
00093 struct KdToDo
00094 {
00095 const kdTreeNode *node;
00096 PFLOAT tmin, tmax;
00097 };
00098
00099 class splitCost_t
00100 {
00101 public:
00102 splitCost_t(): bestAxis(-1), bestOffset(-1) {};
00103 int bestAxis;
00104 int bestOffset;
00105 float bestCost;
00106 float oldCost;
00107 PFLOAT t;
00108 int nBelow, nAbove, nEdge;
00109 };
00110
00111 class bin_t
00112 {
00113 public:
00114 bin_t(): n(0), c_left(0), c_right(0), c_bleft(0), c_both(0) {};
00115 bool empty(){ return n==0; };
00116 void reset(){n=0, c_left=0, c_right=0, c_both=0, c_bleft=0;};
00117 int n;
00118 int c_left, c_right;
00119 int c_bleft, c_both;
00120 PFLOAT t;
00121 };
00122
00123
00127 class YAFRAYCORE_EXPORT triKdTree_t
00128 {
00129 public:
00130 triKdTree_t(const triangle_t **v, int np, int depth=-1, int leafSize=2,
00131 float cost_ratio=0.35, float emptyBonus=0.33);
00132 bool Intersect(const ray_t &ray, PFLOAT dist, triangle_t **tr, PFLOAT &Z, void *udat) const;
00133
00134 bool IntersectS(const ray_t &ray, PFLOAT dist, triangle_t **tr) const;
00135 bool IntersectTS(renderState_t &state, const ray_t &ray, int maxDepth, PFLOAT dist, triangle_t **tr, color_t &filt) const;
00136
00137 bound_t getBound(){ return treeBound; }
00138 ~triKdTree_t();
00139 private:
00140 void pigeonMinCost(u_int32 nPrims, bound_t &nodeBound, u_int32 *primIdx, splitCost_t &split);
00141 void minimalCost(u_int32 nPrims, bound_t &nodeBound, u_int32 *primIdx,
00142 const bound_t *allBounds, boundEdge *edges[3], splitCost_t &split);
00143 int buildTree(u_int32 nPrims, bound_t &nodeBound, u_int32 *primNums,
00144 u_int32 *leftPrims, u_int32 *rightPrims, boundEdge *edges[3],
00145 u_int32 rightMemSize, int depth, int badRefines );
00146
00147 float costRatio;
00148 float eBonus;
00149 u_int32 nextFreeNode, allocatedNodesCount, totalPrims;
00150 int maxDepth;
00151 unsigned int maxLeafSize;
00152 bound_t treeBound;
00153 MemoryArena primsArena;
00154 kdTreeNode *nodes;
00155
00156
00157 const triangle_t **prims;
00158 bound_t *allBounds;
00159 int *clip;
00160 char *cdata;
00161
00162
00163 int depthLimitReached, NumBadSplits;
00164 };
00165
00166
00167 __END_YAFRAY
00168 #endif //__Y_KDTREE_H