Files
PhotonMF/kd_tree.hpp

183 lines
6.0 KiB
C++

#include <vector>
#include <limits>
#include <iostream>
#include <glm/glm.hpp>
#include "rgbe.hpp"
enum superKey
{
XYZ,
YZX,
ZXY,
};
struct Vec3
{
float x;
float y;
float z;
Vec3(float _x = 0.0f, float _y = 0.0f, float _z = 0.0f): x(_x), y(_y), z(_z) { }
Vec3(const Vec3 & other) = default;
glm::vec3 toVec3() {
return glm::vec3(x, y, z);
}
inline bool equalFloat(const float x, const float y)
{
return (x - std::numeric_limits<float>::epsilon() <= y) && (x + std::numeric_limits<float>::epsilon() >= y);
}
inline bool operator<=(const Vec3 b)
{
return (x < b.x || (equalFloat(x, b.x) && (y < b.y || (equalFloat(y, b.y) && z <= b.z))));
}
inline bool operator>=(const Vec3 b)
{
return (x > b.x || (equalFloat(x, b.x) && (y > b.y || (equalFloat(y, b.y) && z >= b.z))));
}
inline friend std::ostream& operator<<(std::ostream& out, const Vec3& v)
{
return out << "X:" << v.x << " Y:" << v.y << " Z:" << v.z;
}
};
struct Photon
{
Vec3 position;
Vec3 direction;
float ref_index;
unsigned char radiance[4];
float r, g, b;
Photon(Vec3 _p = Vec3(), Vec3 _d = Vec3(), float red = 0.0f, float green = 0.0f, float blue = 0.0f, float _r = 1.0f):
position(_p),
direction(_d),
ref_index(_r),
r(red),
g(green),
b(blue)
{
float2rgbe(radiance, red, green, blue);
}
inline void getColor(float & red, float & green, float & blue) {
rgbe2float(red, green, blue, radiance);
}
inline bool equalFloat(const float x, const float y)
{
return (x - std::numeric_limits<float>::epsilon() <= y) && (x + std::numeric_limits<float>::epsilon() >= y);
}
inline bool operator==(const Photon p)
{
return equalFloat(position.x, p.position.x) && equalFloat(position.y, p.position.y) && equalFloat(position.z, p.position.z);
}
inline bool lessEqual(const Photon& b, superKey key)
{
return (key == XYZ && (position.x < b.position.x || (equalFloat(position.x, b.position.x) && (position.y < b.position.y || (equalFloat(position.y, b.position.y) && position.z <= b.position.z)))))
|| (key == YZX && (position.y < b.position.y || (equalFloat(position.y, b.position.y) && (position.z < b.position.z || (equalFloat(position.z, b.position.z) && position.x <= b.position.x)))))
|| (key == ZXY && (position.z < b.position.z || (equalFloat(position.z, b.position.z) && (position.x < b.position.x || (equalFloat(position.x, b.position.x) && position.y <= b.position.y)))));
}
inline bool lower(const Photon &b, superKey key)
{
return (key == XYZ && (position.x < b.position.x || (equalFloat(position.x, b.position.x) && (position.y < b.position.y || (equalFloat(position.y, b.position.y) && position.z < b.position.z)))))
|| (key == YZX && (position.y < b.position.y || (equalFloat(position.y, b.position.y) && (position.z < b.position.z || (equalFloat(position.z, b.position.z) && position.x < b.position.x)))))
|| (key == ZXY && (position.z < b.position.z || (equalFloat(position.z, b.position.z) && (position.x < b.position.x || (equalFloat(position.x, b.position.x) && position.y < b.position.y)))));
}
inline bool greater(const Photon &b, superKey key)
{
return (key == XYZ && (position.x > b.position.x || (equalFloat(position.x, b.position.x) && (position.y > b.position.y || (equalFloat(position.y, b.position.y) && position.z > b.position.z)))))
|| (key == YZX && (position.y > b.position.y || (equalFloat(position.y, b.position.y) && (position.z > b.position.z || (equalFloat(position.z, b.position.z) && position.x > b.position.x)))))
|| (key == ZXY && (position.z > b.position.z || (equalFloat(position.z, b.position.z) && (position.x > b.position.x || (equalFloat(position.x, b.position.x) && position.y > b.position.y)))));
}
inline friend std::ostream& operator<<(std::ostream& out, const Photon& p)
{
return out << "Position: " << p.position;
}
};
class treeNode
{
private:
Photon photon;
bool haveChilds;
superKey cutPlane;
treeNode* leftChild;
treeNode* rightChild;
public:
treeNode(Photon p, superKey plane);
~treeNode();
inline bool operator==(treeNode b);
inline bool operator>(treeNode b);
inline bool operator<(treeNode b);
inline bool operator==(Photon p);
inline bool operator>(Photon p);
inline bool operator<(Photon p);
inline bool operator>=(Vec3 p);
inline bool operator<=(Vec3 p);
inline friend std::ostream& operator<<(std::ostream& out, treeNode &t)
{
out << "Cut Plane ";
switch(*(t.getCutPlane()))
{
case XYZ:
out << "X ";
break;
case YZX:
out << "Y ";
break;
case ZXY:
out << "Z ";
break;
}
return out << "Photon " << *(t.getPhoton()) << " HaveChilds: " << *(t.getChildsFlag());
}
Photon* getPhoton(){return &photon;}
bool* getChildsFlag(){return &haveChilds;}
void setChildsFlag(bool childs){haveChilds = childs;}
superKey* getCutPlane(){return &cutPlane;}
treeNode** getLeftChild(){return &leftChild;}
treeNode** getRightChild(){return &rightChild;}
};
//Clase que genera el kdTree
class kdTree
{
public:
kdTree();
~kdTree();
void addPhoton(Photon p);
bool buildKdTree();
void printTree();
std::vector<Photon> findInRange (Vec3 min, Vec3 max) const;
void find_by_distance(std::vector<Photon> & found, const glm::vec3 & point, const glm::vec3 & normal, const float distance, const unsigned int max) const;
void save_photon_list(const char * file_name) const;
size_t getNumPhotons();
private:
treeNode* root;
std::vector<Photon> Photons;
void createNodeKdTree(treeNode** node, std::vector<Photon> originalData , int xyz[], int yzx[], int zxy[], superKey key, int begin, int end, int fullsize);
void reorderArrays(std::vector<Photon> originalData, int A1[], int A2[], int begin, int mid, int end, int orderIndex, superKey key);
void removeDuplicates(std::vector<Photon> &originalData, int* &xyz, int* &yzx, int* &zxy, int &size);
void printNode(treeNode* node);
void findInRange (Vec3 min, Vec3 max, std::vector<Photon> & photons, treeNode *node) const;
};