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