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