00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef LUX_TABRECKDTREEACCEL_H
00024 #define LUX_TABRECKDTREEACCEL_H
00025
00026
00027 #include "lux.h"
00028 #include "primitive.h"
00029 #include "memory.h"
00030
00031 namespace lux
00032 {
00033
00034 struct TaBRecKdAccelNode {
00035
00036 void initLeaf(int *primNums, int np,
00037 boost::shared_ptr<Primitive> *prims, MemoryArena &arena) {
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 nPrims = np << 2;
00048 flags |= 3;
00049
00050 if (np == 0)
00051 onePrimitive = NULL;
00052 else if (np == 1)
00053 onePrimitive = prims[primNums[0]].get();
00054 else {
00055 primitives = (Primitive **)arena.Alloc(np *
00056 sizeof(Primitive **));
00057 for (int i = 0; i < np; ++i)
00058 primitives[i] = prims[primNums[i]].get();
00059 }
00060 }
00061 void initInterior(int axis, float s) {
00062
00063
00064 split = s;
00065 flags &= ~3;
00066 flags |= axis;
00067 }
00068 float SplitPos() const { return split; }
00069 int nPrimitives() const { return nPrims >> 2; }
00070 int SplitAxis() const { return flags & 3; }
00071 bool IsLeaf() const { return (flags & 3) == 3; }
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 union {
00083 u_int flags;
00084 float split;
00085 u_int nPrims;
00086 };
00087 union {
00088 u_int aboveChild;
00089 Primitive *onePrimitive;
00090 Primitive **primitives;
00091 };
00092 };
00093
00094 struct TaBRecBoundEdge {
00095
00096 TaBRecBoundEdge() { }
00097 TaBRecBoundEdge(float tt, int pn, bool starting) {
00098 t = tt;
00099 primNum = pn;
00100 type = starting ? START : END;
00101 }
00102 bool operator<(const TaBRecBoundEdge &e) const {
00103 if (t == e.t)
00104 return (int)type < (int)e.type;
00105 else return t < e.t;
00106 }
00107 float t;
00108 int primNum;
00109 enum { START, END } type;
00110 };
00111
00112
00113
00114
00115
00116 struct TaBRecInverseMailboxes {
00117 int indexFirstFree;
00118 Primitive *mailboxes[8];
00119
00120 TaBRecInverseMailboxes() {
00121 indexFirstFree = 0;
00122 for (u_int i = 0; i < 8; ++i)
00123 mailboxes[i] = NULL;
00124 }
00125
00126 void addChecked(Primitive *p) {
00127 mailboxes[indexFirstFree++] = p;
00128 indexFirstFree &= 0x7;
00129 }
00130
00131 bool alreadyChecked(const Primitive *p) const {
00132 for (u_int i = 0; i < 8; ++i)
00133 if (mailboxes[i] == p)
00134 return true;
00135
00136 return false;
00137 }
00138 };
00139
00140
00141 class TaBRecKdTreeAccel : public Aggregate {
00142 public:
00143
00144 TaBRecKdTreeAccel(const vector<boost::shared_ptr<Primitive> > &p,
00145 int icost, int scost,
00146 float ebonus, int maxp, int maxDepth);
00147 virtual BBox WorldBound() const { return bounds; }
00148 virtual bool CanIntersect() const { return true; }
00149 virtual ~TaBRecKdTreeAccel();
00150 virtual bool Intersect(const Ray &ray, Intersection *isect) const;
00151 virtual bool IntersectP(const Ray &ray) const;
00152
00153 virtual void GetPrimitives(vector<boost::shared_ptr<Primitive> > &prims);
00154
00155 static Aggregate *CreateAccelerator(const vector<boost::shared_ptr<Primitive> > &prims, const ParamSet &ps);
00156
00157 private:
00158 void buildTree(int nodeNum, const BBox &bounds,
00159 const vector<BBox> &primBounds,
00160 int *primNums, int nprims, int depth,
00161 TaBRecBoundEdge *edges[3],
00162 int *prims0, int *prims1, int badRefines = 0);
00163
00164 BBox bounds;
00165 int isectCost, traversalCost, maxPrims;
00166 float emptyBonus;
00167
00168 u_int nPrims;
00169 boost::shared_ptr<Primitive> *prims;
00170 TaBRecKdAccelNode *nodes;
00171 int nAllocedNodes, nextFreeNode;
00172
00173 MemoryArena arena;
00174 };
00175
00176 struct TaBRecKdNodeStack {
00177 const TaBRecKdAccelNode *node;
00178 float t;
00179
00180 Point pb;
00181
00182 int prev;
00183 };
00184
00185 }
00186
00187 #endif
00188