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