File: radiosity.h

package info (click to toggle)
povray 1%3A3.7.0.10-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 147,232 kB
  • sloc: cpp: 845,011; ansic: 122,118; sh: 34,204; pascal: 6,420; asm: 3,355; ada: 1,681; makefile: 1,388; cs: 879; awk: 590; perl: 245; xml: 95
file content (346 lines) | stat: -rw-r--r-- 13,972 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
/*******************************************************************************
 * radiosity.h
 *
 * This file contains radiosity computation classes and types.
 *
 * ---------------------------------------------------------------------------
 * Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
 * Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd.
 *
 * POV-Ray is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * POV-Ray is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * ---------------------------------------------------------------------------
 * POV-Ray is based on the popular DKB raytracer version 2.12.
 * DKBTrace was originally written by David K. Buck.
 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
 * ---------------------------------------------------------------------------
 * $File: //depot/public/povray/3.x/source/backend/lighting/radiosity.h $
 * $Revision: #1 $
 * $Change: 6069 $
 * $DateTime: 2013/11/06 11:59:40 $
 * $Author: chrisc $
 *******************************************************************************/

#ifndef POVRAY_BACKEND_RADIOSITY_H
#define POVRAY_BACKEND_RADIOSITY_H

#include "backend/frame.h"
#include "backend/povray.h"
#include "backend/scene/view.h"
#include "backend/scene/scene.h"
#include "backend/render/tracepixel.h"
#include "backend/render/rendertask.h"
#include "backend/support/octree.h"
#include "backend/support/randomsequences.h"
#include "backend/lighting/photons.h"
#include "backend/interior/media.h"

#include "povrayold.h" // TODO FIXME

#include <vector>

namespace pov
{

class ViewData;

#define RADIOSITY_CACHE_EXTENSION ".rca"

static const unsigned int RADIOSITY_MAX_SAMPLE_DIRECTIONS    = 1600;
// to get some more pseudo-randomness and make use of the full range of all the precomputed sample directions,
// we start each sample direction sequence at a different index than the previous one; 663 has some nice properties for this:
// - it is fairly large stride, only giving "overlap" of consecutive samples at high sample counts
// - it has no divisors in common with 1600, so that any consecutive 1600 samples will start at a different index
// - it gives the highest possible number of "secondary strides", those being -274, 115, -44, -17, -7 and 3

class SceneRadiositySettings;

// settings as effective for a particular bounce depth during a particuar trace step
struct RadiosityRecursionSettings
{
	// true "tweakables"
	unsigned int    raysPerSample;          // number of sample rays to shoot per sample
	unsigned int    reuseCount;             // number of samples required for re-use
	double          errorBoundFactor;       // factor governing spacing of samples in general
	double          minReuseFactor;         // factor governing minimum spacing of samples in creases
	double          maxReuseFactor;         // factor governing maximum spacing of samples in open areas
	double          octreeOverfillFactor;   // factor governing octree lookup performance
	unsigned int    traceLevel;             // base trace level to use for secondary rays
	double          weight;                 // base weight to use for secondary rays

	// precomputed values
	double          maxErrorBound;          // maximum error bound to be expected for sample lookup
	double          octreeAddressFactor;    // effective radius factor for filing samples in the octree
};

// settings as specified in the scene file;
// naming conventions are as per the respective scene file parameter
class SceneRadiositySettings
{
	public:

		// primary settings from the scene file

		bool    radiosityEnabled;

		double  brightness;
		long    count;
		long    directionPoolSize;
		double  errorBound;
		double  grayThreshold;
		double  lowErrorFactor;
		double  minimumReuse;
		bool    minimumReuseSet;
		double  maximumReuse;
		bool    maximumReuseSet;
		long    nearestCount;
		long    nearestCountAPT;
		int     recursionLimit;
		double  maxSample;
		double  adcBailout;
		bool    normal;
		bool    media;
		double  pretraceStart;
		double  pretraceEnd;
		bool    alwaysSample;
		bool    vainPretrace;               // whether to use full quality during pretrace even where it doesn't matter, to give the user a nice show
		float   defaultImportance;
		bool    subsurface;                 // whether to use subsurface scattering for radiosity sampling rays

		SceneRadiositySettings() {
			radiosityEnabled    = false;
			brightness          = 1.0;
			count               = 35;
			directionPoolSize   = RADIOSITY_MAX_SAMPLE_DIRECTIONS;
			errorBound          = 1.8;
			grayThreshold       = 0.0;
			lowErrorFactor      = 0.5;
			minimumReuse        = 0.015;
			minimumReuseSet     = false;
			maximumReuse        = 0.2;
			maximumReuseSet     = false;
			nearestCount        = 5;        // TODO FIXME - let's get rid of this completely
			nearestCountAPT     = 0;        // second nearest_count parameter, governing adaptive pretrace
			recursionLimit      = 2;
			maxSample           = -1.0;     // default max brightness allows any
			adcBailout          = 0.01;
			normal              = false;
			media               = false;
			pretraceStart       = 0.08;
			pretraceEnd         = 0.04;
			alwaysSample        = false;
			vainPretrace        = false;
			defaultImportance   = 1.0;
			subsurface          = false;
		}

		RadiosityRecursionSettings* GetRecursionSettings (bool final) const;
};

class RadiosityCache
{
	private:

		static const unsigned int BLOCK_POOL_UNIT_SIZE = 32;

	public:

		class BlockPool
		{
			friend class RadiosityCache;
			public:
				BlockPool();
				~BlockPool();
			protected:
				OT_BLOCK* NewBlock();
				void Save(OStream *fd);
			private:
				struct PoolUnit
				{
					PoolUnit *next;
					OT_BLOCK blocks[BLOCK_POOL_UNIT_SIZE];
					PoolUnit(PoolUnit *n) : next(n) { }
				};
				PoolUnit *head;                 // newest pool unit
				PoolUnit *savedHead;            // newest block that has been saved completely
				unsigned int nextFreeBlock;     // next free block (in *head)
				unsigned int nextUnsavedBlock;  // next unsaved block (in *savedHead predecessor)
		};

		int firstRadiosityPass;

		long ra_reuse_count;
		long ra_gather_count;

		RGBColour Gather_Total;
		long Gather_Total_Count;

		#ifdef RADSTATS
			extern long ot_blockcount;
			long ot_seenodecount;
			long ot_seeblockcount;
			long ot_doblockcount;
			long ot_dotokcount;
			long ot_lastcount;
			long ot_lowerrorcount;
		#endif

		RadiosityCache(const SceneRadiositySettings& radset);
		~RadiosityCache();

		bool Load(const Path& inputFile);
		void InitAutosave(const Path& outputFile, bool append);

		DBL FindReusableBlock(RenderStatistics& stats, DBL errorbound, const Vector3d& ipoint, const Vector3d& snormal, RGBColour& illuminance, int recursionDepth, int pretraceStep, int tileId);
		BlockPool* AcquireBlockPool();
		void AddBlock(BlockPool* pool, RenderStatistics* stats, const Vector3d& Point, const Vector3d& S_Normal, const Vector3d& To_Nearest_Surface,
		              const RGBColour& dx, const RGBColour& dy, const RGBColour& dz, const RGBColour& Illuminance,
		              DBL Harmonic_Mean_Distance, DBL Nearest_Distance, DBL Quality, int Bounce_Depth, int pretraceStep, int tileId);
		void ReleaseBlockPool(BlockPool* pool);

	private:

		struct Octree
		{
			OT_NODE *root;
			boost::mutex treeMutex;   // lock this when adding nodes to the tree
			boost::mutex blockMutex;  // lock this when adding blocks to any node of the tree

			Octree() : root(NULL) {}
		};

		vector<BlockPool*> blockPools;  // block pools ready to be re-used
		boost::mutex blockPoolsMutex;   // lock this when accessing blockPools

		Octree octree;

		OStream *ot_fd;
		boost::mutex fileMutex;         // lock this when accessing ot_fd

		RadiosityRecursionSettings* recursionSettings; // dynamically allocated array; use recursion depth as index

		void InsertBlock(OT_NODE* node, OT_BLOCK *block);
		OT_NODE *GetNode(RenderStatistics* stats, const OT_ID& id);

		static bool AverageNearBlock(OT_BLOCK *block, void *void_info);
};

class RadiosityFunction : public Trace::RadiosityFunctor
{
	public:

		static const unsigned int TILE_MAX          = OT_TILE_MAX;
		static const unsigned int PRETRACE_INVALID  = OT_PASS_INVALID;
		static const unsigned int PRETRACE_FIRST    = OT_PASS_FIRST;
		static const unsigned int PRETRACE_MAX      = OT_PASS_MAX;
		static const unsigned int FINAL_TRACE       = OT_PASS_FINAL;
		static const unsigned int DEPTH_MAX         = (OT_DEPTH_MAX < 20 ? OT_DEPTH_MAX : 20);
		static const unsigned int MAX_NEAREST_COUNT = 20;

		// initializes radiosity module from:
		//      sd      - pointer to the scene data
		//      td      - pointer to the thread-specific data
		//      rs      - the radiosity settings as parsed from the scene file
		//      rc      - the radiosity cache to retrieve previously computed samples from, and store newly computed samples in
		//      cf      - the cooperate functor (whatever that is - some thing that handles inter-thread communication?)
		//      pts     - number of the current pretrace step (PRETRACE_FIRST to PRETRACE_MAX, or FINAL_TRACE for main render)
		//      camera  - position of the camera
		RadiosityFunction(shared_ptr<SceneData> sd, TraceThreadData *td,
		                  const SceneRadiositySettings& rs, RadiosityCache& rc, Trace::CooperateFunctor& cf, bool ft, const Vector3d& camera);
		virtual ~RadiosityFunction();

		// looks up the ambient value for a certain point
		//      ipoint          - point on the surface
		//      raw_normal      - the geometry raw norml at this pont
		//      layer_normal    - texture-pertubed normal
		//      ambient_colour  - (output) the ambient color at this point
		//      weight          - the base "weight" of the traced ray (used to compare againgst ADC bailout)
		virtual void ComputeAmbient(const Vector3d& ipoint, const Vector3d& raw_normal, const Vector3d& layer_normal, RGBColour& ambient_colour, DBL weight, Trace::TraceTicket& ticket);

		// checks whether the specified recursion depth is still within the configured limits
		virtual bool CheckRadiosityTraceLevel(const Trace::TraceTicket& ticket);

		// retrieves top level statistics information to drive pretrace re-iteration
		virtual void GetTopLevelStats(long& queryCount, float& reuse);
		virtual void ResetTopLevelStats();
		virtual void BeforeTile(int id, unsigned int pts = FINAL_TRACE);
		virtual void AfterTile();

	private:

		class SampleDirectionGenerator
		{
			public:
				/// constructor
				SampleDirectionGenerator();
				/// Called before each tile
				void Reset(unsigned int samplePoolCount);
				/// Called before each sample
				void InitSequence(unsigned int& sample_count, const Vector3d& raw_normal, const Vector3d& layer_normal, bool use_raw_normal);
				/// Called to get the next sampling ray direction
				bool GetDirection(Vector3d& direction);
			protected:
				/// number of remaining directions to try
				size_t remainingDirections;
				/// whether we're using the raw surface normal instead of the pertubed normal
				bool rawNormalMode;
				/// the raw surface normal // TODO FIXME - for smooth triangles etc. this *should* be *really* raw, but it isn't!
				Vector3d rawNormal;
				/// direction we'll map the precomputed sample directions' X axis to
				Vector3d frameX;
				/// direction we'll map the precomputed sample directions' Y axis to (the effective normal vector)
				Vector3d frameY;
				/// direction we'll map the precomputed sample directions' Z axis to
				Vector3d frameZ;
				/// Generator for sampling directions
				SequentialVectorGeneratorPtr sampleDirections;
		};

		// structure to store precomputed effective parameters for each recursion depth
		struct RecursionParameters
		{
			SampleDirectionGenerator directionGenerator;    // sample generator for this recursion depth
			IntStatsIndex statsId;                          // statistics id for per-pass per-recursion statistics
			IntStatsIndex queryCountStatsId;                // statistics id for per-recursion statistics
			FPStatsIndex weightStatsId;                     // statistics id for per-recursion statistics
		};

		// The modules that do the actual computing
		// (we use our own instances for the sake of thread-safety)

		Trace trace;                        // does the main raytracing
		MediaFunction media;                // computes media effects
		PhotonGatherer photonGatherer;      // computes photon-based illumination

		// Local data

		TraceThreadData *threadData;
		RadiosityCache& radiosityCache;     // this is where we retrieve previously computed samples from, and store newly computed samples in
		RadiosityCache::BlockPool* cacheBlockPool;
		DBL errorBound;                     // the error_bound setting
		bool isFinalTrace;
		unsigned int pretraceStep;
		Vector3d cameraPosition;
		const SceneRadiositySettings&       settings;
		const RadiosityRecursionSettings*   recursionSettings;      // dynamically allocated array; use recursion depth as index
		RecursionParameters*                recursionParameters;    // dynamically allocated array; use recursion depth as index
		long topLevelQueryCount;
		float topLevelReuse;
		int tileId;

		double GatherLight(const Vector3d& IPoint, const Vector3d& Raw_Normal, const Vector3d& LayNormal, RGBColour& Illuminance, Trace::TraceTicket& ticket);
};

} // end of namespace

#endif // POVRAY_BACKEND_RADIOSITY_H