00001 #ifndef _Accelerators_h__
00002 #define _Accelerators_h__
00003
00004 #include "fv_float.h"
00005 #include "types.h"
00006 #include "Object.h"
00007 #include "Geometry.h"
00008 #include "ElemId.hpp"
00009 #include "MathHelper.h"
00010 #include "BBox3D.h"
00011 #include "Enums.h"
00012 #include "ArrayT.hpp"
00013
00014 #include <vector>
00015 #include <stdlib.h>
00016 #include <stdint.h>
00017 #include <string.h>
00018 #include "ocl.h"
00019
00020 namespace FemViewer {
00021
00022
00023
00024 class RContext;
00025 class Mesh;
00026 class Field;
00027 struct IsectData;
00028 template<typename TReal,typename TIndex, unsigned N> class mfvObject;
00029
00030
00031 using namespace fvmath;
00032 template<class t> class Ray;
00033
00034 class Accelerator
00035 {
00036 public:
00037
00038 Accelerator(const RContext* rc,const char* name_);
00039 virtual ~Accelerator(void) {}
00040 virtual const mfvBaseObject* intersect(const Ray<float>& ray, el_isect_info_t *isecData) const;
00041 virtual void dump(void) const {}
00042 virtual void drawOn(bool On = true) {}
00043 virtual void insert(BBox3D&,CVec3f&,ElemId<id_t>) {}
00044 const RContext *context;
00045 const char* name;
00046 Object object;
00047
00048 };
00049
00050 class BVH : public Accelerator
00051 {
00052
00053 static const uint8_t kNumPlaneSetNormals = 3 ;
00054 static const CVec3f planeSetNormals[kNumPlaneSetNormals];
00055
00056 struct Extents
00057 {
00058 Extents() : object(0), id(-1) {
00059 for (uint8_t i = 0; i < kNumPlaneSetNormals; ++i)
00060 d[i][0] = kInfinity, d[i][1] = -kInfinity;
00061 }
00062
00063 void operator =(const BBox3D& bbox) {
00064 assert(bbox.isInitialized());
00065 d[0][0] = bbox.mn.x; d[0][1] = bbox.mx.x;
00066 d[1][0] = bbox.mn.y; d[1][1] = bbox.mx.y;
00067 d[2][0] = bbox.mn.z; d[2][1] = bbox.mx.z;
00068 extbbox = bbox;
00069 }
00070 void extendBy(const Extents &extents)
00071 {
00072 for (uint8_t i = 0; i < kNumPlaneSetNormals; ++i) {
00073 if (extents.d[i][0] < d[i][0]) d[i][0] = extents.d[i][0];
00074 if (extents.d[i][1] > d[i][1]) d[i][1] = extents.d[i][1];
00075 }
00076 extbbox += extents.extbbox;
00077 }
00078 bool intersect(
00079 const float *precomputedNumerator,
00080 const float *precomputeDenominator,
00081 float &tNear, float &tFar, uint8_t &planeIndex);
00082 float d[kNumPlaneSetNormals][2];
00083 const mfvBaseObject *object;
00084 int id;
00085
00086 BBox3D extbbox;
00087 };
00088 Extents *extents;
00089 struct OctreeNode
00090 {
00091 OctreeNode *child[8];
00092 std::vector<const Extents *> data;
00093 Extents extents;
00094 bool isLeaf;
00095 uint8_t depth;
00096 OctreeNode() : isLeaf(true) {
00097 memset(child, 0x0, sizeof(OctreeNode *) * 8);
00098 }
00099 ~OctreeNode() { for (uint8_t i = 0; i < 8; ++i) if (child[i] != NULL) delete child[i]; }
00100 };
00101 struct Octree
00102 {
00103 Octree(const BBox3D &bbox,Object& obj) : root(NULL),object(obj)
00104 {
00105 float sizes[3];
00106 uint8_t dim = bbox.majorAxis(sizes);
00107 CVec3f centroid(
00108 (bbox.mn.x + bbox.mx.x),
00109 (bbox.mn.y + bbox.mx.y),
00110 (bbox.mn.z + bbox.mx.z));
00111 bounds[0] = (centroid - CVec3f(sizes[dim],sizes[dim],sizes[dim])) * 0.5f;
00112 bounds[1] = (centroid + CVec3f(sizes[dim],sizes[dim],sizes[dim])) * 0.5f;
00113 root = new OctreeNode;
00114 }
00115 void insert(const Extents *extents) { insert(root, extents, bounds[0], bounds[1], 0); }
00116 void build() { build(root, bounds[0], bounds[1]); }
00117 void render() { render(root); }
00118 void drawOn(bool On);
00119 ~Octree() { delete root; }
00120 struct QueueElement
00121 {
00122 const OctreeNode *node;
00123 float t;
00124 QueueElement(const OctreeNode *n, float thit) : node(n), t(thit) {}
00125
00126 friend bool operator < (const QueueElement &a, const QueueElement &b) { return a.t > b.t; }
00127 };
00128 CVec3f bounds[2];
00129 OctreeNode *root;
00130 Object& object;
00131 private:
00132 void insert(
00133 OctreeNode *node, const Extents *extents,
00134 CVec3f boundMin, CVec3f boundMax, int depth)
00135 {
00136 if (node->isLeaf) {
00137 if (node->data.size() == 0 || depth == 16) {
00138 node->data.push_back(extents);
00139 }
00140 else {
00141 node->isLeaf = false;
00142 while (node->data.size()) {
00143 insert(node, node->data.back(), boundMin, boundMax, depth);
00144 node->data.pop_back();
00145 }
00146 insert(node, extents, boundMin, boundMax, depth);
00147 }
00148 }
00149 else {
00150
00151 CVec3f extentsCentroid = (
00152 CVec3f(extents->d[0][0], extents->d[1][0], extents->d[2][0]) +
00153 CVec3f(extents->d[0][1], extents->d[1][1], extents->d[2][1])) * 0.5f;
00154
00155 CVec3f nodeCentroid = (boundMax + boundMin) * 0.5f;
00156 CVec3f childBoundMin, childBoundMax;
00157 uint8_t childIndex = 0;
00158 if (extentsCentroid[0] > nodeCentroid[0]) {
00159 childIndex = 4;
00160 childBoundMin[0] = nodeCentroid[0];
00161 childBoundMax[0] = boundMax[0];
00162 }
00163 else {
00164 childBoundMin[0] = boundMin[0];
00165 childBoundMax[0] = nodeCentroid[0];
00166 }
00167 if (extentsCentroid[1] > nodeCentroid[1]) {
00168 childIndex += 2;
00169 childBoundMin[1] = nodeCentroid[1];
00170 childBoundMax[1] = boundMax[1];
00171 }
00172 else {
00173 childBoundMin[1] = boundMin[1];
00174 childBoundMax[1] = nodeCentroid[1];
00175 }
00176 if (extentsCentroid[2] > nodeCentroid[2]) {
00177 childIndex += 1;
00178 childBoundMin[2] = nodeCentroid[2];
00179 childBoundMax[2] = boundMax[2];
00180 }
00181 else {
00182 childBoundMin[2] = boundMin[2];
00183 childBoundMax[2] = nodeCentroid[2];
00184 }
00185 if (node->child[childIndex] == NULL)
00186 node->child[childIndex] = new OctreeNode, node->child[childIndex]->depth = depth;
00187 insert(node->child[childIndex], extents, childBoundMin, childBoundMax, depth + 1);
00188 }
00189 }
00190
00191 void build(OctreeNode *node, const CVec3f &boundMin, const CVec3f &boundMax)
00192 {
00193 if (node->isLeaf) {
00194
00195 for (uint32_t i = 0; i < node->data.size(); ++i) {
00196 node->extents.extendBy(*node->data[i]);
00197 }
00198 }
00199 else {
00200 for (uint8_t i = 0; i < 8; ++i)
00201 if (node->child[i]) {
00202 CVec3f pMin, pMax;
00203 CVec3f pMid = (boundMin + boundMax) * 0.5f;
00204 pMin[0] = (i & 4) ? pMid[0] : boundMin[0];
00205 pMax[0] = (i & 4) ? boundMax[0] : pMid[0];
00206 pMin[1] = (i & 2) ? pMid[1] : boundMin[1];
00207 pMax[1] = (i & 2) ? boundMax[1] : pMid[1];
00208 pMin[2] = (i & 1) ? pMid[2] : boundMin[2];
00209 pMax[2] = (i & 1) ? boundMax[2] : pMid[2];
00210 build(node->child[i], pMin, pMax);
00211 node->extents.extendBy(node->child[i]->extents);
00212 }
00213 }
00214 }
00215
00216 void render(OctreeNode *node);
00217
00218
00219
00220 };
00221
00222 void render() { octree->render(); };
00223 Octree *octree;
00224
00225
00226
00227 public:
00228 BVH(const RContext *rcx);
00229 const mfvBaseObject * intersect(const Ray<float>& ray, el_isect_info_t &isectData) const;
00230 void drawOn(bool On = true) { octree->drawOn(On); }
00231 ~BVH();
00232 };
00233
00234
00235 class Grid : public Accelerator
00236 {
00237 static const float density;
00238 static CVec3f calcResolution(const BBox3D& rbox,const uint32_t nelems,uint32_t res[]);
00239
00240 template<class T>
00241 struct MyContainer : std::vector<T> {
00242 CompareBndAct<T> myComp;
00243 void segregate() {
00244 std::sort(this->begin(),this->end(), myComp);
00245 }
00246 };
00247
00248 template<class T,class TContainer = MyContainer<T> >
00249 struct CellItem
00250 {
00251
00252
00253
00254 CellItem() : color(), count(0) {}
00255
00256 void insert(const ElemInfo &info) {
00257 vElems.push_back(info);
00258 }
00259
00260 void insert(const ElemId<id_t> &ID) {
00261 vElems.push_back(ID);
00262 }
00263
00264 void segregate() {
00265 vElems.segregate();
00266 }
00267
00268 bool intersect(const Ray<float> &ray, const mfvBaseObject **) const;
00269
00270 TContainer vElems;
00271 CVec3f color;
00272 uint32_t count;
00273 };
00274
00275 typedef CellItem<ElemId<id_t>, ArrayT<id_t,ElemId<id_t> > > Cell;
00276
00277 public:
00278 Grid(const RContext *rcx);
00279 Grid(const RContext* rcx,const BBox3D& bbox,uint32_t nEls);
00280 ~Grid() {
00281 for (uint32_t i = 0; i < resolution[0] * resolution[1] * resolution[2]; ++i)
00282 if (cells[i] != NULL) delete cells[i];
00283 delete [] cells;
00284 if (C != NULL) delete [] C;
00285 if (L != NULL) delete [] L;
00286 }
00287 Cell* operator()(uint_t x,uint_t y,uint_t z) {
00288 uint32_t o = z * resolution[0] * resolution[1] + y * resolution[0] + x;
00289 if (!cells[o]) cells[o] = new Cell;
00290 return cells[o];
00291 }
00292 void test(BBox3D& elBBox,fvmath::CVec3f& center);
00293 void create();
00294 void segregate();
00295 void insert(BBox3D& elBBox,CVec3f& center,ElemId<id_t> ID);
00296 void PackElems(std::vector<CoordType>& ElCoords,
00297 std::vector<float>& ElCoefs,
00298 std::vector<uint32_t>& Cells);
00299 const mfvBaseObject* intersect(const Ray<float> &ray, isect_info_t &isectData) const;
00300 void render (void);
00301 void drawOn(bool On = true);
00302 void dump(void) const;
00303 Cell **cells;
00304 BBox3D bbox;
00305 const uint32_t numElems;
00306 uint32_t resolution[3];
00307 CVec3f cellDimension;
00308 uint32_t* C;
00309 uint32_t* L;
00310
00311 };
00312
00313 struct gridinfo_t {
00314 fvmath::Vec3f minDimension;
00315 fvmath::Vec3f maxDimension;
00316 fvmath::Vec3f cellSize;
00317 fvmath::Vec3i cellCount;
00318 };
00319
00320 int create_grid(double targetoccupancy,
00321 uint32_t numelems,
00322 const BBox3D& gbox,
00323 const BBox3D* boxes,
00324 cl_int** griddata,
00325 cl_int** tridata,
00326 gridinfo_t* gridinfo);
00327
00328
00329 }
00330
00331 #endif