1 #pragma once
2 
3 #ifndef Y_PHOTONMAP_H
4 #define Y_PHOTONMAP_H
5 
6 #include <yafray_constants.h>
7 
8 #include "pkdtree.h"
9 #include <core_api/color.h>
10 
11 __BEGIN_YAFRAY
12 #define c255Ratio 81.16902097686662123083
13 #define c256Ratio 40.74366543152520595687
14 
15 
16 #define cInv255Ratio 0.01231997119054820878
17 #define cInv256Ratio 0.02454369260617025968
18 
19 
20 class dirConverter_t
21 {
22 	public:
23 		dirConverter_t();
24 
convert(unsigned char theta,unsigned char phi)25 		vector3d_t convert(unsigned char theta,unsigned char phi)
26 		{
27 			return vector3d_t(sintheta[theta]*cosphi[phi],
28 								sintheta[theta]*sinphi[phi],
29 								costheta[theta]);
30 		}
convert(const vector3d_t & dir)31 		std::pair<unsigned char,unsigned char> convert(const vector3d_t &dir)
32 		{
33 			int t=(int)(fAcos(dir.z)*c255Ratio);
34 			int p=(int)(atan2(dir.y,dir.x)*c256Ratio);
35 			if(t>254) t=254;
36 			else if(t<0) t=0;
37 			if(p>255) p=255;
38 			else if(p<0) p+=256;
39 			return std::pair<unsigned char,unsigned char>(t,p);
40 		}
41 
42 	protected:
43 		float cosphi[256];
44 		float sinphi[256];
45 		float costheta[255];
46 		float sintheta[255];
47 };
48 
49 extern YAFRAYCORE_EXPORT dirConverter_t dirconverter;
50 
51 class photon_t
52 {
53 	public:
photon_t()54 		photon_t() {/*theta=255;*/};
photon_t(const vector3d_t & d,const point3d_t & p,const color_t & col)55 		photon_t(const vector3d_t &d,const point3d_t &p, const color_t &col)
56 		{
57 #ifdef _SMALL_PHOTONS
58 			direction(d);
59 #else
60 			dir=d;
61 #endif
62 			pos=p;
63 			c=col;
64 		};
65 //		photon_t(const runningPhoton_t &p)
66 //		{
67 //			pos=p.pos;
68 //			c=p.c;
69 //			vector3d_t dir=p.lastpos-p.pos;
70 //			dir.normalize();
71 //			direction(dir);
72 //		};
position()73 		const point3d_t & position()const {return pos;};
color()74 		const color_t color()const {return c;};
color(const color_t & col)75 		void color(const color_t &col) {c=col;};
direction()76 		vector3d_t direction()const
77 		{
78 #ifdef _SMALL_PHOTONS
79 			if(theta==255) return vector3d_t(0,0,0);
80 			else return dirconverter.convert(theta,phi);
81 #else //_SMALL_PHOTONS
82 			return (vector3d_t)dir;
83 #endif //_SMALL_PHOTONS
84 		};
direction(const vector3d_t & d)85 		void direction(const vector3d_t &d)
86 		{
87 #ifdef _SMALL_PHOTONS
88 			if(dir.null()) theta=255;
89 			else
90 			{
91 				std::pair<unsigned char,unsigned char> cd=dirconverter.convert(d);
92 				theta=cd.first;
93 				phi=cd.second;
94 			}
95 #else //_SMALL_PHOTONS
96 			dir=d;
97 #endif //_SMALL_PHOTONS
98 		}
99 
100 		point3d_t pos;
101 
102 #ifdef _SMALL_PHOTONS
103 		rgbe_t c;
104 		unsigned char theta,phi;
105 
106 #else //_SMALL_PHOTONS
107 		color_t c;
108 		normal_t dir;
109 #endif //_SMALL_PHOTONS
110 };
111 
112 struct radData_t
113 {
radData_tradData_t114 	radData_t(point3d_t &p, vector3d_t n): pos(p), normal(n), use(true) {}
115 	point3d_t pos;
116 	vector3d_t normal;
117 	color_t refl;
118 	color_t transm;
119 	mutable bool use;
120 };
121 
122 struct foundPhoton_t
123 {
foundPhoton_tfoundPhoton_t124 	foundPhoton_t(){};
foundPhoton_tfoundPhoton_t125 	foundPhoton_t(const photon_t *p, float d): photon(p), distSquare(d){}
126 	bool operator<(const foundPhoton_t &p2) const { return distSquare < p2.distSquare; }
127 	const photon_t *photon;
128 	float distSquare;
129 	//temp!!
130 	float dis;
131 };
132 
133 class YAFRAYCORE_EXPORT photonMap_t
134 {
135 	public:
photonMap_t()136 		photonMap_t(): paths(0), updated(false), searchRadius(1.), tree(nullptr){ }
photonMap_t(const std::string & mapname,int threads)137 		photonMap_t(const std::string &mapname, int threads): paths(0), updated(false), searchRadius(1.), tree(nullptr), name(mapname),threadsPKDtree(threads) { }
~photonMap_t()138 		~photonMap_t(){ if(tree) delete tree; }
setNumPaths(int n)139 		void setNumPaths(int n){ paths=n; }
setName(const std::string & mapname)140 		void setName(const std::string &mapname) { name = mapname; }
setNumThreadsPKDtree(int threads)141 		void setNumThreadsPKDtree(int threads){ threadsPKDtree = threads; }
nPaths()142 		int nPaths() const{ return paths; }
nPhotons()143 		int nPhotons() const{ return photons.size(); }
pushPhoton(photon_t & p)144 		void pushPhoton(photon_t &p) { photons.push_back(p); updated=false; }
swapVector(std::vector<photon_t> & vec)145 		void swapVector(std::vector<photon_t> &vec) { photons.swap(vec); updated=false; }
appendVector(std::vector<photon_t> & vec,unsigned int curr)146 		void appendVector(std::vector<photon_t> &vec, unsigned int curr) { photons.insert(std::end(photons), std::begin(vec), std::end(vec)); updated=false; paths += curr;}
reserveMemory(size_t numPhotons)147 		void reserveMemory(size_t numPhotons) { photons.reserve(numPhotons); }
148 		void updateTree();
clear()149 		void clear(){ photons.clear(); delete tree; tree = nullptr; updated=false; }
ready()150 		bool ready() const { return updated; }
151 	//	void gather(const point3d_t &P, std::vector< foundPhoton_t > &found, unsigned int K, float &sqRadius) const;
152 		int gather(const point3d_t &P, foundPhoton_t *found, unsigned int K, float &sqRadius) const;
153 		const photon_t* findNearest(const point3d_t &P, const vector3d_t &n, float dist) const;
154 		bool load(const std::string &filename);
155 		bool save(const std::string &filename) const;
156 		std::mutex mutx;
157 
158 	protected:
159 		std::vector<photon_t> photons;
160 		int paths; //!< amount of photon paths that have been traced for generating the map
161 		bool updated;
162 		float searchRadius;
163 		kdtree::pointKdTree<photon_t> *tree;
164 		std::string name;
165 		int threadsPKDtree = 1;
166 };
167 
168 // photon "processes" for lookup
169 
170 struct photonGather_t
171 {
172 	photonGather_t(uint32_t mp, const point3d_t &p);
173 	void operator()(const photon_t *photon, float dist2, float &maxDistSquared) const;
174 	const point3d_t &p;
175 	foundPhoton_t *photons;
176 	uint32_t nLookup;
177 	mutable uint32_t foundPhotons;
178 };
179 
180 struct nearestPhoton_t
181 {
nearestPhoton_tnearestPhoton_t182 	nearestPhoton_t(const point3d_t &pos, const vector3d_t &norm): p(pos), n(norm), nearest(nullptr) {}
operatornearestPhoton_t183 	void operator()(const photon_t *photon, float dist2, float &maxDistSquared) const
184 	{
185 		if ( photon->direction() * n > 0.f) { nearest = photon; maxDistSquared = dist2; }
186 	}
187 	const point3d_t p; //wth do i need this for actually??
188 	const vector3d_t n;
189 	mutable const photon_t *nearest;
190 };
191 
192 /*! "eliminates" photons within lookup radius (sets use=false) */
193 struct eliminatePhoton_t
194 {
eliminatePhoton_teliminatePhoton_t195 	eliminatePhoton_t(const vector3d_t &norm): n(norm) {}
operatoreliminatePhoton_t196 	void operator()(const radData_t *rpoint, float dist2, float &maxDistSquared) const
197 	{
198 		if ( rpoint->normal * n > 0.f) { rpoint->use = false; }
199 	}
200 	const vector3d_t n;
201 };
202 
203 __END_YAFRAY
204 
205 #endif // Y_PHOTONMAP_H
206