00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "lux.h"
00026 #include "primitive.h"
00027 #include <boost/pool/object_pool.hpp>
00028
00029 namespace lux
00030 {
00031
00032
00033 struct GMailboxPrim;
00034 struct Voxel;
00035
00036
00037 struct GMailboxPrim {
00038 GMailboxPrim(boost::shared_ptr<Primitive> p) {
00039 primitive = p;
00040 lastMailboxId = -1;
00041 }
00042 boost::shared_ptr<Primitive> primitive;
00043 int lastMailboxId;
00044 };
00045
00046
00047
00048 struct Voxel {
00049
00050 Voxel(GMailboxPrim *op) {
00051 allCanIntersect = false;
00052 nPrimitives = 1;
00053 onePrimitive = op;
00054 }
00055 void AddPrimitive(GMailboxPrim *prim) {
00056 if (nPrimitives == 1) {
00057
00058 GMailboxPrim **p = new GMailboxPrim *[2];
00059 p[0] = onePrimitive;
00060 primitives = p;
00061 }
00062 else if (IsPowerOf2(nPrimitives)) {
00063
00064 int nAlloc = 2 * nPrimitives;
00065 GMailboxPrim **p = new GMailboxPrim *[nAlloc];
00066 for (u_int i = 0; i < nPrimitives; ++i)
00067 p[i] = primitives[i];
00068 delete[] primitives;
00069 primitives = p;
00070 }
00071 primitives[nPrimitives] = prim;
00072 ++nPrimitives;
00073 }
00074 ~Voxel() {
00075 if (nPrimitives > 1) delete[] primitives;
00076 }
00077 bool Intersect(const Ray &ray,
00078 Intersection *isect,
00079 int rayId);
00080 bool IntersectP(const Ray &ray, int rayId);
00081 union {
00082 GMailboxPrim *onePrimitive;
00083 GMailboxPrim **primitives;
00084 };
00085 u_int allCanIntersect:1;
00086 u_int nPrimitives:31;
00087 };
00088
00089 class GridAccel : public Aggregate {
00090 public:
00091
00092 GridAccel(const vector<boost::shared_ptr<Primitive> > &p,
00093 bool forRefined, bool refineImmediately);
00094 virtual BBox WorldBound() const;
00095 virtual bool CanIntersect() const { return true; }
00096 virtual ~GridAccel();
00097 virtual bool Intersect(const Ray &ray, Intersection *isect) const;
00098 virtual bool IntersectP(const Ray &ray) const;
00099
00100 virtual void GetPrimitives(vector<boost::shared_ptr<Primitive> > &prims);
00101
00102 static Aggregate *CreateAccelerator(const vector<boost::shared_ptr<Primitive> > &prims, const ParamSet &ps);
00103 private:
00104
00105 int PosToVoxel(const Point &P, int axis) const {
00106 int v = Float2Int((P[axis] - bounds.pMin[axis]) *
00107 InvWidth[axis]);
00108 return Clamp(v, 0, NVoxels[axis]-1);
00109 }
00110 float VoxelToPos(int p, int axis) const {
00111 return bounds.pMin[axis] + p * Width[axis];
00112 }
00113 Point VoxelToPos(int x, int y, int z) const {
00114 return bounds.pMin +
00115 Vector(x * Width[0], y * Width[1], z * Width[2]);
00116 }
00117 inline int Offset(int x, int y, int z) const {
00118 return z*NVoxels[0]*NVoxels[1] + y*NVoxels[0] + x;
00119 }
00120
00121 bool gridForRefined;
00122 u_int nMailboxes;
00123 GMailboxPrim *mailboxes;
00124 int NVoxels[3];
00125 BBox bounds;
00126 Vector Width, InvWidth;
00127 Voxel **voxels;
00128
00129
00130 boost::object_pool<Voxel> voxelArena;
00131 static int curMailboxId;
00132 };
00133
00134 }
00135