1 /*******************************************************************************
2  * radiosity.h
3  *
4  * This file contains radiosity computation classes and types.
5  *
6  * ---------------------------------------------------------------------------
7  * Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
8  * Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd.
9  *
10  * POV-Ray is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Affero General Public License as
12  * published by the Free Software Foundation, either version 3 of the
13  * License, or (at your option) any later version.
14  *
15  * POV-Ray is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Affero General Public License for more details.
19  *
20  * You should have received a copy of the GNU Affero General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  * ---------------------------------------------------------------------------
23  * POV-Ray is based on the popular DKB raytracer version 2.12.
24  * DKBTrace was originally written by David K. Buck.
25  * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
26  * ---------------------------------------------------------------------------
27  * $File: //depot/public/povray/3.x/source/backend/lighting/radiosity.h $
28  * $Revision: #1 $
29  * $Change: 6069 $
30  * $DateTime: 2013/11/06 11:59:40 $
31  * $Author: chrisc $
32  *******************************************************************************/
33 
34 #ifndef POVRAY_BACKEND_RADIOSITY_H
35 #define POVRAY_BACKEND_RADIOSITY_H
36 
37 #include "backend/frame.h"
38 #include "backend/povray.h"
39 #include "backend/scene/view.h"
40 #include "backend/scene/scene.h"
41 #include "backend/render/tracepixel.h"
42 #include "backend/render/rendertask.h"
43 #include "backend/support/octree.h"
44 #include "backend/support/randomsequences.h"
45 #include "backend/lighting/photons.h"
46 #include "backend/interior/media.h"
47 
48 #include "povrayold.h" // TODO FIXME
49 
50 #include <vector>
51 
52 namespace pov
53 {
54 
55 class ViewData;
56 
57 #define RADIOSITY_CACHE_EXTENSION ".rca"
58 
59 static const unsigned int RADIOSITY_MAX_SAMPLE_DIRECTIONS    = 1600;
60 // to get some more pseudo-randomness and make use of the full range of all the precomputed sample directions,
61 // we start each sample direction sequence at a different index than the previous one; 663 has some nice properties for this:
62 // - it is fairly large stride, only giving "overlap" of consecutive samples at high sample counts
63 // - it has no divisors in common with 1600, so that any consecutive 1600 samples will start at a different index
64 // - it gives the highest possible number of "secondary strides", those being -274, 115, -44, -17, -7 and 3
65 
66 class SceneRadiositySettings;
67 
68 // settings as effective for a particular bounce depth during a particuar trace step
69 struct RadiosityRecursionSettings
70 {
71 	// true "tweakables"
72 	unsigned int    raysPerSample;          // number of sample rays to shoot per sample
73 	unsigned int    reuseCount;             // number of samples required for re-use
74 	double          errorBoundFactor;       // factor governing spacing of samples in general
75 	double          minReuseFactor;         // factor governing minimum spacing of samples in creases
76 	double          maxReuseFactor;         // factor governing maximum spacing of samples in open areas
77 	double          octreeOverfillFactor;   // factor governing octree lookup performance
78 	unsigned int    traceLevel;             // base trace level to use for secondary rays
79 	double          weight;                 // base weight to use for secondary rays
80 
81 	// precomputed values
82 	double          maxErrorBound;          // maximum error bound to be expected for sample lookup
83 	double          octreeAddressFactor;    // effective radius factor for filing samples in the octree
84 };
85 
86 // settings as specified in the scene file;
87 // naming conventions are as per the respective scene file parameter
88 class SceneRadiositySettings
89 {
90 	public:
91 
92 		// primary settings from the scene file
93 
94 		bool    radiosityEnabled;
95 
96 		double  brightness;
97 		long    count;
98 		long    directionPoolSize;
99 		double  errorBound;
100 		double  grayThreshold;
101 		double  lowErrorFactor;
102 		double  minimumReuse;
103 		bool    minimumReuseSet;
104 		double  maximumReuse;
105 		bool    maximumReuseSet;
106 		long    nearestCount;
107 		long    nearestCountAPT;
108 		int     recursionLimit;
109 		double  maxSample;
110 		double  adcBailout;
111 		bool    normal;
112 		bool    media;
113 		double  pretraceStart;
114 		double  pretraceEnd;
115 		bool    alwaysSample;
116 		bool    vainPretrace;               // whether to use full quality during pretrace even where it doesn't matter, to give the user a nice show
117 		float   defaultImportance;
118 		bool    subsurface;                 // whether to use subsurface scattering for radiosity sampling rays
119 
SceneRadiositySettings()120 		SceneRadiositySettings() {
121 			radiosityEnabled    = false;
122 			brightness          = 1.0;
123 			count               = 35;
124 			directionPoolSize   = RADIOSITY_MAX_SAMPLE_DIRECTIONS;
125 			errorBound          = 1.8;
126 			grayThreshold       = 0.0;
127 			lowErrorFactor      = 0.5;
128 			minimumReuse        = 0.015;
129 			minimumReuseSet     = false;
130 			maximumReuse        = 0.2;
131 			maximumReuseSet     = false;
132 			nearestCount        = 5;        // TODO FIXME - let's get rid of this completely
133 			nearestCountAPT     = 0;        // second nearest_count parameter, governing adaptive pretrace
134 			recursionLimit      = 2;
135 			maxSample           = -1.0;     // default max brightness allows any
136 			adcBailout          = 0.01;
137 			normal              = false;
138 			media               = false;
139 			pretraceStart       = 0.08;
140 			pretraceEnd         = 0.04;
141 			alwaysSample        = false;
142 			vainPretrace        = false;
143 			defaultImportance   = 1.0;
144 			subsurface          = false;
145 		}
146 
147 		RadiosityRecursionSettings* GetRecursionSettings (bool final) const;
148 };
149 
150 class RadiosityCache
151 {
152 	private:
153 
154 		static const unsigned int BLOCK_POOL_UNIT_SIZE = 32;
155 
156 	public:
157 
158 		class BlockPool
159 		{
160 			friend class RadiosityCache;
161 			public:
162 				BlockPool();
163 				~BlockPool();
164 			protected:
165 				OT_BLOCK* NewBlock();
166 				void Save(OStream *fd);
167 			private:
168 				struct PoolUnit
169 				{
170 					PoolUnit *next;
171 					OT_BLOCK blocks[BLOCK_POOL_UNIT_SIZE];
PoolUnitPoolUnit172 					PoolUnit(PoolUnit *n) : next(n) { }
173 				};
174 				PoolUnit *head;                 // newest pool unit
175 				PoolUnit *savedHead;            // newest block that has been saved completely
176 				unsigned int nextFreeBlock;     // next free block (in *head)
177 				unsigned int nextUnsavedBlock;  // next unsaved block (in *savedHead predecessor)
178 		};
179 
180 		int firstRadiosityPass;
181 
182 		long ra_reuse_count;
183 		long ra_gather_count;
184 
185 		RGBColour Gather_Total;
186 		long Gather_Total_Count;
187 
188 		#ifdef RADSTATS
189 			extern long ot_blockcount;
190 			long ot_seenodecount;
191 			long ot_seeblockcount;
192 			long ot_doblockcount;
193 			long ot_dotokcount;
194 			long ot_lastcount;
195 			long ot_lowerrorcount;
196 		#endif
197 
198 		RadiosityCache(const SceneRadiositySettings& radset);
199 		~RadiosityCache();
200 
201 		bool Load(const Path& inputFile);
202 		void InitAutosave(const Path& outputFile, bool append);
203 
204 		DBL FindReusableBlock(RenderStatistics& stats, DBL errorbound, const Vector3d& ipoint, const Vector3d& snormal, RGBColour& illuminance, int recursionDepth, int pretraceStep, int tileId);
205 		BlockPool* AcquireBlockPool();
206 		void AddBlock(BlockPool* pool, RenderStatistics* stats, const Vector3d& Point, const Vector3d& S_Normal, const Vector3d& To_Nearest_Surface,
207 		              const RGBColour& dx, const RGBColour& dy, const RGBColour& dz, const RGBColour& Illuminance,
208 		              DBL Harmonic_Mean_Distance, DBL Nearest_Distance, DBL Quality, int Bounce_Depth, int pretraceStep, int tileId);
209 		void ReleaseBlockPool(BlockPool* pool);
210 
211 	private:
212 
213 		struct Octree
214 		{
215 			OT_NODE *root;
216 			boost::mutex treeMutex;   // lock this when adding nodes to the tree
217 			boost::mutex blockMutex;  // lock this when adding blocks to any node of the tree
218 
OctreeOctree219 			Octree() : root(NULL) {}
220 		};
221 
222 		vector<BlockPool*> blockPools;  // block pools ready to be re-used
223 		boost::mutex blockPoolsMutex;   // lock this when accessing blockPools
224 
225 		Octree octree;
226 
227 		OStream *ot_fd;
228 		boost::mutex fileMutex;         // lock this when accessing ot_fd
229 
230 		RadiosityRecursionSettings* recursionSettings; // dynamically allocated array; use recursion depth as index
231 
232 		void InsertBlock(OT_NODE* node, OT_BLOCK *block);
233 		OT_NODE *GetNode(RenderStatistics* stats, const OT_ID& id);
234 
235 		static bool AverageNearBlock(OT_BLOCK *block, void *void_info);
236 };
237 
238 class RadiosityFunction : public Trace::RadiosityFunctor
239 {
240 	public:
241 
242 		static const unsigned int TILE_MAX          = OT_TILE_MAX;
243 		static const unsigned int PRETRACE_INVALID  = OT_PASS_INVALID;
244 		static const unsigned int PRETRACE_FIRST    = OT_PASS_FIRST;
245 		static const unsigned int PRETRACE_MAX      = OT_PASS_MAX;
246 		static const unsigned int FINAL_TRACE       = OT_PASS_FINAL;
247 		static const unsigned int DEPTH_MAX         = (OT_DEPTH_MAX < 20 ? OT_DEPTH_MAX : 20);
248 		static const unsigned int MAX_NEAREST_COUNT = 20;
249 
250 		// initializes radiosity module from:
251 		//      sd      - pointer to the scene data
252 		//      td      - pointer to the thread-specific data
253 		//      rs      - the radiosity settings as parsed from the scene file
254 		//      rc      - the radiosity cache to retrieve previously computed samples from, and store newly computed samples in
255 		//      cf      - the cooperate functor (whatever that is - some thing that handles inter-thread communication?)
256 		//      pts     - number of the current pretrace step (PRETRACE_FIRST to PRETRACE_MAX, or FINAL_TRACE for main render)
257 		//      camera  - position of the camera
258 		RadiosityFunction(shared_ptr<SceneData> sd, TraceThreadData *td,
259 		                  const SceneRadiositySettings& rs, RadiosityCache& rc, Trace::CooperateFunctor& cf, bool ft, const Vector3d& camera);
260 		virtual ~RadiosityFunction();
261 
262 		// looks up the ambient value for a certain point
263 		//      ipoint          - point on the surface
264 		//      raw_normal      - the geometry raw norml at this pont
265 		//      layer_normal    - texture-pertubed normal
266 		//      ambient_colour  - (output) the ambient color at this point
267 		//      weight          - the base "weight" of the traced ray (used to compare againgst ADC bailout)
268 		virtual void ComputeAmbient(const Vector3d& ipoint, const Vector3d& raw_normal, const Vector3d& layer_normal, RGBColour& ambient_colour, DBL weight, Trace::TraceTicket& ticket);
269 
270 		// checks whether the specified recursion depth is still within the configured limits
271 		virtual bool CheckRadiosityTraceLevel(const Trace::TraceTicket& ticket);
272 
273 		// retrieves top level statistics information to drive pretrace re-iteration
274 		virtual void GetTopLevelStats(long& queryCount, float& reuse);
275 		virtual void ResetTopLevelStats();
276 		virtual void BeforeTile(int id, unsigned int pts = FINAL_TRACE);
277 		virtual void AfterTile();
278 
279 	private:
280 
281 		class SampleDirectionGenerator
282 		{
283 			public:
284 				/// constructor
285 				SampleDirectionGenerator();
286 				/// Called before each tile
287 				void Reset(unsigned int samplePoolCount);
288 				/// Called before each sample
289 				void InitSequence(unsigned int& sample_count, const Vector3d& raw_normal, const Vector3d& layer_normal, bool use_raw_normal);
290 				/// Called to get the next sampling ray direction
291 				bool GetDirection(Vector3d& direction);
292 			protected:
293 				/// number of remaining directions to try
294 				size_t remainingDirections;
295 				/// whether we're using the raw surface normal instead of the pertubed normal
296 				bool rawNormalMode;
297 				/// the raw surface normal // TODO FIXME - for smooth triangles etc. this *should* be *really* raw, but it isn't!
298 				Vector3d rawNormal;
299 				/// direction we'll map the precomputed sample directions' X axis to
300 				Vector3d frameX;
301 				/// direction we'll map the precomputed sample directions' Y axis to (the effective normal vector)
302 				Vector3d frameY;
303 				/// direction we'll map the precomputed sample directions' Z axis to
304 				Vector3d frameZ;
305 				/// Generator for sampling directions
306 				SequentialVectorGeneratorPtr sampleDirections;
307 		};
308 
309 		// structure to store precomputed effective parameters for each recursion depth
310 		struct RecursionParameters
311 		{
312 			SampleDirectionGenerator directionGenerator;    // sample generator for this recursion depth
313 			IntStatsIndex statsId;                          // statistics id for per-pass per-recursion statistics
314 			IntStatsIndex queryCountStatsId;                // statistics id for per-recursion statistics
315 			FPStatsIndex weightStatsId;                     // statistics id for per-recursion statistics
316 		};
317 
318 		// The modules that do the actual computing
319 		// (we use our own instances for the sake of thread-safety)
320 
321 		Trace trace;                        // does the main raytracing
322 		MediaFunction media;                // computes media effects
323 		PhotonGatherer photonGatherer;      // computes photon-based illumination
324 
325 		// Local data
326 
327 		TraceThreadData *threadData;
328 		RadiosityCache& radiosityCache;     // this is where we retrieve previously computed samples from, and store newly computed samples in
329 		RadiosityCache::BlockPool* cacheBlockPool;
330 		DBL errorBound;                     // the error_bound setting
331 		bool isFinalTrace;
332 		unsigned int pretraceStep;
333 		Vector3d cameraPosition;
334 		const SceneRadiositySettings&       settings;
335 		const RadiosityRecursionSettings*   recursionSettings;      // dynamically allocated array; use recursion depth as index
336 		RecursionParameters*                recursionParameters;    // dynamically allocated array; use recursion depth as index
337 		long topLevelQueryCount;
338 		float topLevelReuse;
339 		int tileId;
340 
341 		double GatherLight(const Vector3d& IPoint, const Vector3d& Raw_Normal, const Vector3d& LayNormal, RGBColour& Illuminance, Trace::TraceTicket& ticket);
342 };
343 
344 } // end of namespace
345 
346 #endif // POVRAY_BACKEND_RADIOSITY_H
347