1 /*******************************************************************************
2  * view.h
3  *
4  * ---------------------------------------------------------------------------
5  * Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
6  * Copyright 1991-2013 Persistence of Vision Raytracer Pty. Ltd.
7  *
8  * POV-Ray is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Affero General Public License as
10  * published by the Free Software Foundation, either version 3 of the
11  * License, or (at your option) any later version.
12  *
13  * POV-Ray is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Affero General Public License for more details.
17  *
18  * You should have received a copy of the GNU Affero General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  * ---------------------------------------------------------------------------
21  * POV-Ray is based on the popular DKB raytracer version 2.12.
22  * DKBTrace was originally written by David K. Buck.
23  * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
24  * ---------------------------------------------------------------------------
25  * $File: //depot/public/povray/3.x/source/backend/scene/view.h $
26  * $Revision: #1 $
27  * $Change: 6069 $
28  * $DateTime: 2013/11/06 11:59:40 $
29  * $Author: chrisc $
30  *******************************************************************************/
31 
32 #ifndef POVRAY_BACKEND_VIEW_H
33 #define POVRAY_BACKEND_VIEW_H
34 
35 #include <vector>
36 
37 #include "base/povmscpp.h"
38 #include "base/types.h"
39 #include "backend/povray.h"
40 #include "backend/support/taskqueue.h"
41 #include "backend/scene/camera.h"
42 #include "backend/scene/scene.h"
43 #include "backend/control/renderbackend.h"
44 #include "backend/lighting/photons.h"
45 #include "backend/lighting/radiosity.h"
46 
47 #include "povrayold.h" //TODO
48 
49 namespace pov
50 {
51 
52 using namespace pov_base;
53 
54 class Renderer;
55 
56 class View;
57 class Scene;
58 
59 class ViewData;
60 class SceneData;
61 class ViewThreadData;
62 
63 class RTRData
64 {
65 	public:
66 		RTRData(ViewData& v, int mrt);
67 		~RTRData();
68 
69 		/// wait for other threads to complete the current frame. returns the new camera if it's to change.
70 		const Camera *CompletedFrame();
71 		/// number of frames rendered in real-time raytracing mode
72 		unsigned int numRTRframes;
73 		/// this holds the pixels rendered in real-time-raytracing mode
74 		vector<POVMSFloat> rtrPixels;
75 		/// the number of render threads to wait for
76 		int numRenderThreads;
77 		/// the number of render threads that have completed the current RTR frame
78 		volatile int numRenderThreadsCompleted;
79 
80 	private:
81 		ViewData& viewData;
82 		boost::mutex counterMutex;
83 		boost::mutex eventMutex;
84 		boost::condition event;
85 		int width;
86 		int height;
87 		unsigned int numPixelsCompleted;
88 };
89 
90 /**
91  *	ViewData class representing holding view specific data.
92  *	For private use by View and Renderer classes only!
93  *	Unlike scene data, dependencies on direct access to
94  *	view specific data members has been removed, and as
95  *	such there are no public members but only accessor
96  *	methods. Please do not add public data members!!!
97  */
98 class ViewData
99 {
100 		// View needs access to the private view data constructor as well
101 		// as some private data in order to initialise it properly!
102 		friend class View;
103 	public:
104 		/**
105 		 *  Container for information about a rectangle to be retained between passes.
106 		 *  To be subclasses by trace tasks.
107 		 */
108 		class BlockInfo
109 		{
110 			public:
~BlockInfo()111 				virtual ~BlockInfo() {} // need to have a virtual member so we can use dynamic_cast
112 		};
113 
114 		/**
115 		 *  Get the next sub-rectangle of the view to render (if any).
116 		 *  This method is called by the render threads when they have
117 		 *  completed rendering one block and are ready to start rendering
118 		 *  the next block.
119 		 *  @param  rect            Rectangle to render.
120 		 *  @param  serial          Rectangle serial number.
121 		 *  @return                 True if there is another rectangle to be dispatched, false otherwise.
122 		 */
123 		bool GetNextRectangle(POVRect& rect, unsigned int& serial);
124 
125 		/**
126 		 *  Get the next sub-rectangle of the view to render (if any).
127 		 *  This method is called by the render threads when they have
128 		 *  completed rendering one block and are ready to start rendering
129 		 *  the next block.
130 		 *  Avoids rectangles with certain offsets from busy rectangles.
131 		 *  @param  rect            Rectangle to render.
132 		 *  @param  serial          Rectangle serial number.
133 		 *  @param  blockInfo       Additional information about the rectangle.
134 		 *                          NULL if the block is being dispatched for the first time.
135 		 *  @param  stride          Avoid-Busy stride. If this value is non-zero, any blocks following a busy block
136 		 *                          with an offset of a multiple of this value will not be dispatched until the busy block
137 		 *                          has been completed.
138 		 *  @return                 True if there is another rectangle ready to be dispatched, false otherwise.
139 		 */
140 		bool GetNextRectangle(POVRect& rect, unsigned int& serial, BlockInfo*& blockInfo, unsigned int stride);
141 
142 		/**
143 		 *  Called to (fully or partially) complete rendering of a specific sub-rectangle of the view.
144 		 *  The pixel data is sent to the frontend and pixel progress information
145 		 *  is updated and sent to the frontend.
146 		 *  @param  rect            Rectangle just completed.
147 		 *  @param  serial          Serial number of rectangle just completed.
148 		 *  @param  pixels          Pixels of completed rectangle.
149 		 *  @param  size            Size of each pixel (width and height).
150 		 *  @param  final           Mark the block as completely rendered for continue-trace.
151 		 *  @param  completion      Approximate contribution of current pass to completion of this rectangle.
152 		 *  @param  blockInfo       Pointer to additional information about the rectangle. If this value is non-NULL,
153 		 *                          the rectangle will be scheduled to be re-dispatched for another pass, and the
154 		 *                          data passed to whichever rendering thread the rectangle will be re-dispatched to.
155 		 *                          If this value is NULL, the rectangle will not be re-dispatched.
156 		 */
157 		void CompletedRectangle(const POVRect& rect, unsigned int serial, const vector<Colour>& pixels, unsigned int size, bool final, float completion = 1.0, BlockInfo* blockInfo = NULL);
158 
159 		/**
160 		 *  Called to (fully or partially) complete rendering of a specific sub-rectangle of the view.
161 		 *  The pixel data is sent to the frontend and pixel progress information
162 		 *  is updated and sent to the frontend.
163 		 *  @param  rect            Rectangle just completed.
164 		 *  @param  serial          Serial number of rectangle just completed.
165 		 *  @param  positions       Pixel positions within rectangle.
166 		 *  @param  colors          Pixel colors for each pixel position.
167 		 *  @param  size            Size of each pixel (width and height).
168 		 *  @param  final           Mark the block as completely rendered for continue-trace.
169 		 *  @param  completion      Approximate contribution of current pass to completion of this rectangle.
170 		 *  @param  blockInfo       Pointer to additional information about the rectangle. If this value is non-NULL,
171 		 *                          the rectangle will be scheduled to be re-dispatched for another pass, and the
172 		 *                          data passed to whichever rendering thread the rectangle will be re-dispatched to.
173 		 *                          If this value is NULL, the rectangle will not be re-dispatched.
174 		 */
175 		void CompletedRectangle(const POVRect& rect, unsigned int serial, const vector<Vector2d>& positions, const vector<Colour>& colors, unsigned int size, bool final, float completion = 1.0, BlockInfo* blockInfo = NULL);
176 
177 		/**
178 		 *  Called to (fully or partially) complete rendering of a specific sub-rectangle of the view without updating pixel data.
179 		 *  Pixel progress information is updated and sent to the frontend.
180 		 *  @param  rect            Rectangle just completed.
181 		 *  @param  serial          Serial number of rectangle just completed.
182 		 *  @param  completion      Approximate contribution of current pass to completion of this rectangle.
183 		 *  @param  blockInfo       Pointer to additional information about the rectangle. If this value is non-NULL,
184 		 *                          the rectangle will be scheduled to be re-dispatched for another pass, and the
185 		 *                          data passed to whichever rendering thread the rectangle will be re-dispatched to.
186 		 *                          If this value is NULL, the rectangle will not be re-dispatched.
187 		 */
188 		void CompletedRectangle(const POVRect& rect, unsigned int serial, float completion = 1.0, BlockInfo* blockInfo = NULL);
189 
190 		/**
191 		 *  Set the blocks not to generate with GetNextRectangle because they have
192 		 *  already been rendered.
193 		 *  @param  bsl             Block serial numbers to skip.
194 		 *  @param  fs              First block to start with checking with serial number.
195 		 */
196 		void SetNextRectangle(const std::set<unsigned int>& bsl, unsigned int fs);
197 
198 		/**
199 		 *  Get width of view in pixels.
200 		 *  @return                 Width in pixels.
201 		 */
GetWidth()202 		inline unsigned int GetWidth() const { return width; }
203 
204 		/**
205 		 *  Get height of view in pixels.
206 		 *  @return                 Height in pixels.
207 		 */
GetHeight()208 		inline unsigned int GetHeight() const { return height; }
209 
210 		/**
211 		 *  Get area of view to be rendered in pixels.
212 		 *  @return                 Area rectangle in pixels.
213 		 */
GetRenderArea()214 		inline const POVRect& GetRenderArea() const { return renderArea; }
215 
216 		/**
217 		 *  Get the camera for this view.
218 		 *  @return                 Current camera.
219 		 */
GetCamera()220 		inline const Camera& GetCamera() const { return camera; }
221 
222 		/**
223 		 *  Get the scene data for this view.
224 		 *  @return                 Scene data.
225 		 */
GetSceneData()226 		inline shared_ptr<SceneData>& GetSceneData() { return sceneData; }
227 
228 		/**
229 		 *  Get the view id for this view.
230 		 *  @return                 View id.
231 		 */
GetViewId()232 		inline RenderBackend::ViewId GetViewId() { return viewId; } // TODO FIXME - more like a hack, need a better way to do this
233 
234 		/**
235 		 *  Get the highest trace level found when last rendering this view.
236 		 *  @return                 Highest trace level found so far.
237 		 */
238 		unsigned int GetHighestTraceLevel();
239 
240 		/**
241 		 *  Set the highest trace level found while rendering this view.
242 		 *  @param  htl				Highest trace level found so far.
243 		 */
244 		void SetHighestTraceLevel(unsigned int htl);
245 
246 		/**
247 		 *  Get the render qualitiy features to use when rendering this view.
248 		 *  @return                 Quality feature flags.
249 		 */
250 		 unsigned int GetQualityFeatureFlags();
251 
252 		/**
253 		 *  Get the radiosity cache.
254 		 *  @return                 Radiosity cache.
255 		 */
256 		 RadiosityCache& GetRadiosityCache();
257 
258 		/**
259 		 *  Get the value of the real-time raytracing option
260 		 *  @return                 true if RTR was requested in render options
261 		 */
GetRealTimeRaytracing()262 		 bool GetRealTimeRaytracing() { return realTimeRaytracing; }
263 
264 		/**
265 		 *  Return a pointer to the real-time raytracing data
266 		 *  @return                 pointer to instance of class RTRData, or NULL if RTR is not enabled
267 		 */
GetRTRData()268 		 RTRData *GetRTRData() { return rtrData; }
269 
270 	private:
271 
272 		struct BlockPostponedEntry {
273 			unsigned int blockId;
274 			unsigned int pass;
BlockPostponedEntryBlockPostponedEntry275 			BlockPostponedEntry(unsigned int id, unsigned int p) : blockId(id), pass(p) {}
276 		};
277 
278 		/// pixels pending
279 		volatile unsigned int pixelsPending;
280 		/// pixels completed
281 		volatile unsigned int pixelsCompleted;
282 		/// Next block counter for algorithm to distribute parts of the scene to render threads.
283 		/// @note   Blocks with higher serial numbers may be dispatched out-of-order for certain reasons;
284 		///         in that case, the dispatched block must be entered into @c blockSkipList instead of
285 		///         advancing this variable.
286 		/// @note   When advancing this variable, the new value should be checked against @c blockSkipList;
287 		///         if the value is in the list, it should be removed, and this variable advanced again,
288 		///         repeating the process until a value is reached that is not found in @c blockSkipList.
289 		volatile unsigned int nextBlock;
290 		/// next block counter mutex
291 		boost::mutex nextBlockMutex;
292 		/// set data mutex
293 		boost::mutex setDataMutex;
294 		/// Whether all blocks have been dispatched at least once.
295 		bool completedFirstPass;
296 		/// highest reached trace level
297 		unsigned int highestTraceLevel;
298 		/// width of view
299 		unsigned int width;
300 		/// height of view
301 		unsigned int height;
302 		/// width of view in blocks
303 		unsigned int blockWidth;
304 		/// height of view in blocks
305 		unsigned int blockHeight;
306 		/// width and height of a block
307 		unsigned int blockSize;
308 		/// List of blocks already rendered out-of-order.
309 		/// This list holds the serial numbers of all blocks ahead of nextBlock
310 		/// that have already been rendered in a previous aborted render now being continued.
311 		std::set<unsigned int> blockSkipList;
312 		/// list of blocks currently rendering
313 		std::set<unsigned int> blockBusyList;
314 		/// list of blocks postponed for some reason
315 		std::set<unsigned int> blockPostponedList;
316 		/// list of additional block information
317 		vector<BlockInfo*> blockInfoList;
318 		/// area of view to be rendered
319 		POVRect renderArea;
320 		/// camera of this view
321 		Camera camera;
322 		/// generated radiosity data
323 		RadiosityCache radiosityCache;
324 		/// scene data
325 		shared_ptr<SceneData> sceneData;
326 		/// view id
327 		RenderBackend::ViewId viewId;
328 
329 		/// true if real-time raytracing is requested (experimental feature)
330 		bool realTimeRaytracing;
331 		/// data specifically associated with the RTR feature
332 		RTRData *rtrData;
333 
334 		/// functions to compute the X & Y block
335 		void getBlockXY(const unsigned int nb, unsigned int &x, unsigned int &y);
336 
337 		/// pattern number to use for rendering
338 		unsigned int renderPattern;
339 
340 		/// adjusted step size for renderering (using clock arithmetic)
341 		unsigned int renderBlockStep;
342 
343 		QualitySettings qualitySettings; // TODO FIXME - put somewhere else or split up
344 
345 		/**
346 		 *  Create view data.
347 		 *  @param  sd              Scene data associated with the view data.
348 		 */
349 		ViewData(shared_ptr<SceneData> sd);
350 
351 		/**
352 		 *  Destructor.
353 		 */
354 		~ViewData();
355 };
356 
357 /**
358  *	View class representing an view with a specific camera
359  *	being rendered.
360  */
361 class View
362 {
363 		// Scene needs access to the private view constructor!
364 		friend class Scene;
365 	public:
366 		/**
367 		 *  Destructor. Rendering will be stopped as necessary.
368 		 */
369 		~View();
370 
371 		/**
372 		 *  Render the view with the specified options. Be
373 		 *  aware that this method is asynchronous! Threads
374 		 *  will be started to perform the parsing and this
375 		 *  method will return. The frontend is notified by
376 		 *  messages of the state of rendering and all warnings
377 		 *  and errors found.
378 		 *  Options shall be in a kPOVObjectClass_RenderOptions
379 		 *  POVMS obect, which is created when parsing the INI
380 		 *  file or command line in the frontend.
381 		 *  @param  renderOptions   Render options to use.
382 		 */
383 		void StartRender(POVMS_Object& renderOptions);
384 
385 		/**
386 		 *  Stop rendering. Rendering may take a few seconds to
387 		 *  stop. Internally stopping is performed by throwing
388 		 *  an exception at well-defined points.
389 		 *  If rendering is not in progress, no action is taken.
390 		 */
391 		void StopRender();
392 
393 		/**
394 		 *  Pause rendering. Rendering may take a few seconds to
395 		 *  pause. Internally pausing is performed by checking
396 		 *  flag at well-defined points, and if it is true, a
397 		 *  loop will repeatedly set the render threads to sleep
398 		 *  for a few milliseconds until the pause flag is
399 		 *  cleared again or rendering is stopped.
400 		 *  If rendering is not in progress, no action is taken.
401 		 */
402 		void PauseRender();
403 
404 		/**
405 		 *  Resume rendering that has previously been stopped.
406 		 *  If rendering is not paussed, no action is taken.
407 		 */
408 		void ResumeRender();
409 
410 		/**
411 		 *  Determine if any render thread is currently running.
412 		 *  @return                 True if any is running, false otherwise.
413 		 */
414 		bool IsRendering();
415 
416 		/**
417 		 *  Determine if rendering is paused. The rendering is considered
418 		 *  paused if at least one render thread is paused.
419 		 *  @return                 True if paused, false otherwise.
420 		 */
421 		bool IsPaused();
422 
423 		/**
424 		 *  Determine if a previously run render thread failed.
425 		 *  @return                 True if failed, false otherwise.
426 		 */
427 		bool Failed();
428 
429 		/**
430 		 *  Get the current render statistics for the view.
431 		 *  Note that this will query each thread, compute the total
432 		 *  and return it.
433 		 *  @param  rect            On return, the current statistics.
434 		 */
435 		void GetStatistics(POVMS_Object& renderStats);
436 	private:
437 		/// running and pending render tasks for this view
438 		TaskQueue renderTasks;
439 		/// view thread data (i.e. statistics)
440 		vector<ViewThreadData *> viewThreadData;
441 		/// view data
442 		ViewData viewData;
443 		/// stop request flag
444 		bool stopRequsted;
445 		/// render control thread
446 		boost::thread *renderControlThread;
447 		/// BSP tree mailbox
448 		BSPTree::Mailbox mailbox;
449 
450 		/// not available
451 		View();
452 
453 		/// not available
454 		View(const View&);
455 
456 		/**
457 		 *  Create an view and associate a scene's data with it.
458 		 *  @param  sd              Scene data to be associated with the view.
459 		 *  @param  width           Width of view in pixels.
460 		 *  @param  height          Height of view in pixels.
461 		 *  @param  vid             Id of this view to include with
462 		 *                          POVMS messages sent to the frontend.
463 		 */
464 		explicit View(shared_ptr<SceneData> sd, unsigned int width, unsigned int height, RenderBackend::ViewId vid);
465 
466 		/// not available
467 		View& operator=(const View&);
468 
469 		/**
470 		 *  Dispatch any shutdown messages appropriate at the end of rendering a view (e.g. max_gradient).
471 		 *  @param  taskq           The task queue that executed this method.
472 		 */
473 		void DispatchShutdownMessages(TaskQueue&);
474 
475 		/**
476 		 *  Send the render statistics upon completion of a render.
477 		 *  @param  taskq           The task queue that executed this method.
478 		 */
479 		void SendStatistics(TaskQueue& taskq);
480 
481 		/**
482 		 *  Set the blocks not to generate with GetNextRectangle because they have
483 		 *  already been rendered.
484 		 *  @param  taskq           The task queue that executed this method.
485 		 *  @param  bsl             Block serial numbers to skip.
486 		 *  @param  fs              First block to start with checking with serial number.
487 		 */
488 		void SetNextRectangle(TaskQueue& taskq, shared_ptr<std::set<unsigned int> > bsl, unsigned int fs);
489 
490 		/**
491 		 *  Thread controlling the render task queue.
492 		 */
493 		void RenderControlThread();
494 
495 		/**
496 		 *  Checks whether or not the point (camera origin) is within a hollow object.
497 		 *  returns true if so. comes in two versions, one for manual iteration of
498 		 *  the object list, and one for a bounding tree.
499 		 */
500 		bool CheckCameraHollowObject(const VECTOR point); // TODO - comment incomplete - consider moving elsewhere [trf]
501 		bool CheckCameraHollowObject(const VECTOR point, const BBOX_TREE *node); // TODO - comment missing - consider moving elsewhere [trf]
502 };
503 
504 }
505 
506 #endif // POVRAY_BACKEND_VIEW_H
507