Blender V2.61 - r43446
|
00001 /* 00002 * Copyright 2011, Blender Foundation. 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 #include "background.h" 00020 #include "buffers.h" 00021 #include "camera.h" 00022 #include "device.h" 00023 #include "integrator.h" 00024 #include "film.h" 00025 #include "light.h" 00026 #include "scene.h" 00027 #include "session.h" 00028 #include "shader.h" 00029 00030 #include "util_color.h" 00031 #include "util_foreach.h" 00032 #include "util_function.h" 00033 #include "util_progress.h" 00034 #include "util_time.h" 00035 00036 #include "blender_sync.h" 00037 #include "blender_session.h" 00038 #include "blender_util.h" 00039 00040 CCL_NAMESPACE_BEGIN 00041 00042 BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::UserPreferences b_userpref_, 00043 BL::BlendData b_data_, BL::Scene b_scene_) 00044 : b_engine(b_engine_), b_userpref(b_userpref_), b_data(b_data_), b_scene(b_scene_), 00045 b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL), 00046 b_rr(PointerRNA_NULL), b_rlay(PointerRNA_NULL) 00047 { 00048 /* offline render */ 00049 BL::RenderSettings r = b_scene.render(); 00050 00051 width = (int)(r.resolution_x()*r.resolution_percentage()/100); 00052 height = (int)(r.resolution_y()*r.resolution_percentage()/100); 00053 background = true; 00054 last_redraw_time = 0.0f; 00055 00056 create_session(); 00057 } 00058 00059 BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::UserPreferences b_userpref_, 00060 BL::BlendData b_data_, BL::Scene b_scene_, 00061 BL::SpaceView3D b_v3d_, BL::RegionView3D b_rv3d_, int width_, int height_) 00062 : b_engine(b_engine_), b_userpref(b_userpref_), b_data(b_data_), b_scene(b_scene_), 00063 b_v3d(b_v3d_), b_rv3d(b_rv3d_), b_rr(PointerRNA_NULL), b_rlay(PointerRNA_NULL) 00064 { 00065 /* 3d view render */ 00066 width = width_; 00067 height = height_; 00068 background = false; 00069 last_redraw_time = 0.0f; 00070 00071 create_session(); 00072 session->start(); 00073 } 00074 00075 BlenderSession::~BlenderSession() 00076 { 00077 free_session(); 00078 } 00079 00080 void BlenderSession::create_session() 00081 { 00082 SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); 00083 SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background); 00084 00085 /* reset status/progress */ 00086 last_status= ""; 00087 last_progress= -1.0f; 00088 00089 /* create scene */ 00090 scene = new Scene(scene_params); 00091 00092 /* create sync */ 00093 sync = new BlenderSync(b_data, b_scene, scene, !background); 00094 sync->sync_data(b_v3d); 00095 00096 if(b_rv3d) 00097 sync->sync_view(b_v3d, b_rv3d, width, height); 00098 else 00099 sync->sync_camera(width, height); 00100 00101 /* create session */ 00102 session = new Session(session_params); 00103 session->scene = scene; 00104 session->progress.set_update_callback(function_bind(&BlenderSession::tag_redraw, this)); 00105 session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this)); 00106 session->set_pause(BlenderSync::get_session_pause(b_scene, background)); 00107 00108 /* set buffer parameters */ 00109 BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height); 00110 session->reset(buffer_params, session_params.samples); 00111 } 00112 00113 void BlenderSession::free_session() 00114 { 00115 delete sync; 00116 delete session; 00117 } 00118 00119 void BlenderSession::render() 00120 { 00121 /* get buffer parameters */ 00122 BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height); 00123 int w = buffer_params.width, h = buffer_params.height; 00124 00125 /* create render result */ 00126 RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, 0, 0, w, h); 00127 PointerRNA rrptr; 00128 RNA_pointer_create(NULL, &RNA_RenderResult, rrp, &rrptr); 00129 b_rr = BL::RenderResult(rrptr); 00130 00131 BL::RenderSettings r = b_scene.render(); 00132 BL::RenderResult::layers_iterator b_iter; 00133 BL::RenderLayers b_rr_layers(r.ptr); 00134 00135 int active = 0; 00136 00137 /* render each layer */ 00138 for(b_rr.layers.begin(b_iter); b_iter != b_rr.layers.end(); ++b_iter, ++active) { 00139 /* single layer render */ 00140 if(r.use_single_layer()) 00141 active = b_rr_layers.active_index(); 00142 00143 /* set layer */ 00144 b_rlay = *b_iter; 00145 00146 /* update scene */ 00147 sync->sync_data(b_v3d, active); 00148 00149 /* render */ 00150 session->start(); 00151 session->wait(); 00152 00153 if(session->progress.get_cancel()) 00154 break; 00155 00156 /* write result */ 00157 write_render_result(); 00158 } 00159 00160 /* delete render result */ 00161 RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data); 00162 } 00163 00164 void BlenderSession::write_render_result() 00165 { 00166 /* get state */ 00167 RenderBuffers *buffers = session->buffers; 00168 float exposure = scene->film->exposure; 00169 double total_time, sample_time; 00170 int sample; 00171 session->progress.get_sample(sample, total_time, sample_time); 00172 00173 /* get pixels */ 00174 float4 *pixels = buffers->copy_from_device(exposure, sample); 00175 00176 if(!pixels) 00177 return; 00178 00179 /* write pixels */ 00180 rna_RenderLayer_rect_set(&b_rlay.ptr, (float*)pixels); 00181 RE_engine_update_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data); 00182 00183 delete [] pixels; 00184 } 00185 00186 void BlenderSession::synchronize() 00187 { 00188 /* on session/scene parameter changes, we recreate session entirely */ 00189 SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); 00190 SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background); 00191 00192 if(session->params.modified(session_params) || 00193 scene->params.modified(scene_params)) { 00194 free_session(); 00195 create_session(); 00196 session->start(); 00197 return; 00198 } 00199 00200 /* increase samples, but never decrease */ 00201 session->set_samples(session_params.samples); 00202 session->set_pause(BlenderSync::get_session_pause(b_scene, background)); 00203 00204 /* copy recalc flags, outside of mutex so we can decide to do the real 00205 synchronization at a later time to not block on running updates */ 00206 sync->sync_recalc(); 00207 00208 /* try to acquire mutex. if we don't want to or can't, come back later */ 00209 if(!session->ready_to_reset() || !session->scene->mutex.try_lock()) { 00210 tag_update(); 00211 return; 00212 } 00213 00214 /* data and camera synchronize */ 00215 sync->sync_data(b_v3d); 00216 00217 if(b_rv3d) 00218 sync->sync_view(b_v3d, b_rv3d, width, height); 00219 else 00220 sync->sync_camera(width, height); 00221 00222 /* unlock */ 00223 session->scene->mutex.unlock(); 00224 00225 /* reset if needed */ 00226 if(scene->need_reset()) { 00227 BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height); 00228 session->reset(buffer_params, session_params.samples); 00229 } 00230 } 00231 00232 bool BlenderSession::draw(int w, int h) 00233 { 00234 /* before drawing, we verify camera and viewport size changes, because 00235 we do not get update callbacks for those, we must detect them here */ 00236 if(session->ready_to_reset()) { 00237 bool reset = false; 00238 00239 /* try to acquire mutex. if we can't, come back later */ 00240 if(!session->scene->mutex.try_lock()) { 00241 tag_update(); 00242 } 00243 else { 00244 /* update camera from 3d view */ 00245 bool need_update = scene->camera->need_update; 00246 00247 sync->sync_view(b_v3d, b_rv3d, w, h); 00248 00249 if(scene->camera->need_update && !need_update) 00250 reset = true; 00251 00252 session->scene->mutex.unlock(); 00253 } 00254 00255 /* if dimensions changed, reset */ 00256 if(width != w || height != h) { 00257 width = w; 00258 height = h; 00259 reset = true; 00260 } 00261 00262 /* reset if requested */ 00263 if(reset) { 00264 SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background); 00265 BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height); 00266 00267 session->reset(buffer_params, session_params.samples); 00268 } 00269 } 00270 00271 /* update status and progress for 3d view draw */ 00272 update_status_progress(); 00273 00274 /* draw */ 00275 BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height); 00276 00277 return !session->draw(buffer_params); 00278 } 00279 00280 void BlenderSession::get_status(string& status, string& substatus) 00281 { 00282 session->progress.get_status(status, substatus); 00283 } 00284 00285 void BlenderSession::get_progress(float& progress, double& total_time) 00286 { 00287 double sample_time; 00288 int sample; 00289 00290 session->progress.get_sample(sample, total_time, sample_time); 00291 progress = ((float)sample/(float)session->params.samples); 00292 } 00293 00294 void BlenderSession::update_status_progress() 00295 { 00296 string status, substatus; 00297 float progress; 00298 double total_time; 00299 char time_str[128]; 00300 00301 get_status(status, substatus); 00302 get_progress(progress, total_time); 00303 00304 BLI_timestr(total_time, time_str); 00305 status = "Elapsed: " + string(time_str) + " | " + status; 00306 00307 if(substatus.size() > 0) 00308 status += " | " + substatus; 00309 00310 if(status != last_status) { 00311 RE_engine_update_stats((RenderEngine*)b_engine.ptr.data, "", status.c_str()); 00312 last_status = status; 00313 } 00314 if(progress != last_progress) { 00315 RE_engine_update_progress((RenderEngine*)b_engine.ptr.data, progress); 00316 last_progress = progress; 00317 } 00318 } 00319 00320 void BlenderSession::tag_update() 00321 { 00322 /* tell blender that we want to get another update callback */ 00323 engine_tag_update((RenderEngine*)b_engine.ptr.data); 00324 } 00325 00326 void BlenderSession::tag_redraw() 00327 { 00328 if(background) { 00329 /* update stats and progress, only for background here because 00330 in 3d view we do it in draw for thread safety reasons */ 00331 update_status_progress(); 00332 00333 /* offline render, redraw if timeout passed */ 00334 if(time_dt() - last_redraw_time > 1.0f) { 00335 write_render_result(); 00336 engine_tag_redraw((RenderEngine*)b_engine.ptr.data); 00337 last_redraw_time = time_dt(); 00338 } 00339 } 00340 else { 00341 /* tell blender that we want to redraw */ 00342 engine_tag_redraw((RenderEngine*)b_engine.ptr.data); 00343 } 00344 } 00345 00346 void BlenderSession::test_cancel() 00347 { 00348 /* test if we need to cancel rendering */ 00349 if(background) 00350 if(RE_engine_test_break((RenderEngine*)b_engine.ptr.data)) 00351 session->progress.set_cancel("Cancelled"); 00352 } 00353 00354 CCL_NAMESPACE_END 00355