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