NVIDIA Index example code nvidia_logo_transpbg.gif Up
parallel_volume_editing.cpp
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright 2023 NVIDIA Corporation. All rights reserved.
3 *****************************************************************************/
6
7#include <mi/dice.h>
8
9// Include code shared by all examples.
10#include "utility/example_shared.h"
11
12#include <nv/index/icamera.h>
13#include <nv/index/icolormap.h>
14#include <nv/index/iindex.h>
15#include <nv/index/iscene.h>
16#include <nv/index/isession.h>
17#include <nv/index/isparse_volume_rendering_properties.h>
18
19#include "utility/app_rendering_context.h"
20#include "utility/canvas_utility.h"
21
22#include <nv/index/app/idata_analysis_and_processing.h>
23#include <nv/index/app/index_connect.h>
24#include <nv/index/app/string_dict.h>
25#include <nv/index/app/time_functions.h>
26
27#include <iostream>
28#include <sstream>
29
30//----------------------------------------------------------------------
32 public nv::index::app::Index_connect
33{
34public:
36 :
37 Index_connect()
38 {
39 // INFO_LOG << "DEBUG: Parallel_volume_editing() ctor";
40 }
41
43 {
44 // Note: Index_connect::~Index_connect() will be called after here.
45 // INFO_LOG << "DEBUG: ~Parallel_volume_editing() dtor";
46 }
47
48 // launch application
49 mi::Sint32 launch();
50
51protected:
52 virtual bool evaluate_options(nv::index::app::String_dict& sdict) CPP11_OVERRIDE;
53 // override
55 mi::neuraylib::INetwork_configuration* network_configuration,
56 nv::index::app::String_dict& options) CPP11_OVERRIDE
57 {
58 check_success(network_configuration != 0);
59
60 check_success(options.is_defined("unittest"));
61 const bool is_unittest = nv::index::app::get_bool(options.get("unittest"));
62 if (is_unittest)
63 {
64 info_cout("NETWORK: disabled networking mode.", options);
65 network_configuration->set_mode(mi::neuraylib::INetwork_configuration::MODE_OFF);
66 return true;
67 }
68
69 return initialize_networking_as_default_udp(network_configuration, options);
70 }
71
72private:
73 // Just create a nice colormap
74 mi::math::Color_struct jetmap(mi::Float32 v, mi::Float32 vmin, mi::Float32 vmax) const;
75 nv::index::IColormap* create_colormap(nv::index::IScene* scene) const;
76 void edit_volume_data(
77 mi::neuraylib::Tag sparse_volume_tag,
78 mi::neuraylib::Tag session_tag,
79 mi::neuraylib::IDice_transaction* dice_transaction) const;
80 // setup camera to see this example scene
81 void setup_camera(nv::index::IPerspective_camera* cam) const;
82 // render a frame
83 // \param[in] output_fname output rendering image filename
84 // \return performance values
85 nv::index::IFrame_results* render_frame(const std::string& output_fname) const;
86
87 // This session tag
88 mi::neuraylib::Tag m_session_tag;
89 // NVIDIA IndeX cluster configuration
90 mi::base::Handle<nv::index::ICluster_configuration> m_cluster_configuration;
91 // Application layer image file canvas (a render target)
92 mi::base::Handle<nv::index::app::canvas_infrastructure::IIndex_image_file_canvas> m_image_file_canvas;
93 // Create_icons options
94 std::string m_outfname;
95 bool m_is_unittest;
96 std::string m_verify_image_fname;
97 std::string m_verify_image_fname_second;
98 bool m_perlin_noise;
99 std::string m_unittest_verify_image_fbase;
100 std::string m_unittest_verify_image_fbase_second;
101};
102
103//----------------------------------------------------------------------
105{
106 mi::Sint32 exit_code = 0;
107
108 // Get DiCE database components
109 {
110 m_cluster_configuration = get_index_interface()->get_api_component<nv::index::ICluster_configuration>();
111 check_success(m_cluster_configuration.is_valid_interface());
112
113 // create image canvas in application_layer
114 m_image_file_canvas = create_image_file_canvas(get_application_layer_interface());
115 check_success(m_image_file_canvas.is_valid_interface());
116
117 // Verifying that local host has joined
118 // This may fail when there is a license problem.
119 check_success(is_local_host_joined(m_cluster_configuration.get()));
120
121 // The volume tag refering the volume for editing.
122 mi::neuraylib::Tag sparse_volume_tag = mi::neuraylib::NULL_TAG;
123
124 // Initialization and scene setup
125 {
126 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
127 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
128 check_success(dice_transaction.is_valid_interface());
129 {
130 // Setup the session and scene.
131 m_session_tag = m_index_session->create_session(dice_transaction.get());
132 check_success(m_session_tag.is_valid());
133
134 // Adjust the global configuration.
135 {
136 // Access the session instance from the database.
137 mi::base::Handle<const nv::index::ISession> session(
138 dice_transaction->access<const nv::index::ISession>(m_session_tag));
139 check_success(session.is_valid_interface());
140 }
141
142 // Create and set up the scene.
143 {
144 // Access the session instance from the database.
145 mi::base::Handle<const nv::index::ISession> session(
146 dice_transaction->access<const nv::index::ISession>(m_session_tag));
147 check_success(session.is_valid_interface());
148
149 // Access (edit mode) the scene instance from the database.
150 mi::base::Handle<nv::index::IScene> scene_edit(
151 dice_transaction->edit<nv::index::IScene>(session->get_scene()));
152 check_success(scene_edit.is_valid_interface());
153
154 // create static group node for large data and append the volume
155 mi::base::Handle<nv::index::IStatic_scene_group> static_group(
156 scene_edit->create_scene_group<nv::index::IStatic_scene_group>());
157 check_success(static_group.is_valid_interface());
158
159 // Parameter to feed the synthetic volume generation technique
160 mi::math::Vector<mi::Uint32, 3> volume_size(1020, 1020, 1020);
161 const mi::math::Bbox<mi::Uint32, 3> bbox(
162 mi::math::Vector<mi::Uint32, 3>(0),
163 volume_size);
164
165 {
166 // Add a sparse_volume_render_properties to the scene.
167 mi::base::Handle<nv::index::ISparse_volume_rendering_properties> sparse_render_prop(
168 scene_edit->create_attribute<nv::index::ISparse_volume_rendering_properties>());
169 sparse_render_prop->set_filter_mode(nv::index::SPARSE_VOLUME_FILTER_NEAREST);
170 sparse_render_prop->set_sampling_distance( 1.0);
171 sparse_render_prop->set_reference_sampling_distance( 1.0);
172 sparse_render_prop->set_voxel_offsets( mi::math::Vector<mi::Float32, 3>(0.5f, 0.5f, 0.5f));
173 sparse_render_prop->set_preintegrated_volume_rendering(false);
174 sparse_render_prop->set_lod_rendering_enabled( false);
175 sparse_render_prop->set_lod_pixel_threshold( 2.0);
176 sparse_render_prop->set_debug_visualization_option( 0);
177 const mi::neuraylib::Tag sparse_render_prop_tag
178 = dice_transaction->store_for_reference_counting(sparse_render_prop.get());
179 check_success(sparse_render_prop_tag.is_valid());
180 static_group->append(sparse_render_prop_tag, dice_transaction.get());
181 INFO_LOG << "Created a sparse_render_prop_tag: tag = " << sparse_render_prop_tag;
182
183 // Add a colormap to the scene
184 mi::base::Handle<nv::index::IColormap> colormap(create_colormap(scene_edit.get()));
185 check_success(colormap.is_valid_interface());
186 const mi::neuraylib::Tag colormap_tag = dice_transaction->store_for_reference_counting(colormap.get());
187 static_group->append(colormap_tag, dice_transaction.get());
188 INFO_LOG << "Add a colormap to the scene: tag = " << colormap_tag;
189 }
190
191 // sparse volume creation parameter
192 nv::index::app::String_dict sparse_volume_opt;
193 sparse_volume_opt.insert("args::type", "sparse_volume");
194 sparse_volume_opt.insert("args::importer", "synthetic");
195 {
196 std::stringstream sstr;
197 sstr << "0 0 0 " << volume_size.x << " " << volume_size.y << " " << volume_size.z;
198 sparse_volume_opt.insert("args::bbox", sstr.str());
199 }
200 sparse_volume_opt.insert("args::voxel_format", "uint8");
201 sparse_volume_opt.insert("args::synthetic_type", "default");
202 if (m_perlin_noise)
203 {
204 sparse_volume_opt.insert("args::synthetic_type", "perlin_noise");
205 sparse_volume_opt.insert("args::parameter::cube_unit", "400");
206 sparse_volume_opt.insert("args::parameter::time", "0");
207 sparse_volume_opt.insert("args::parameter::terms", "5");
208 sparse_volume_opt.insert("args::parameter::turbulence_weight", "1 1 1 1");
209 sparse_volume_opt.insert("args::parameter::abs_noise", "0");
210 sparse_volume_opt.insert("args::parameter::ridged", "1");
211 }
212 nv::index::IDistributed_data_import_callback* generator =
213 get_importer_from_application_layer(
214 get_application_layer_interface(),
215 "nv::index::plugin::base_importer.Sparse_volume_generator_synthetic",
216 sparse_volume_opt);
217
218 // Create a scene element that represents a sparse volume.
219 mi::math::Matrix<mi::Float32, 4, 4> transform_mat(1.0f); // Identity matrix
220
221 const mi::math::Bbox<mi::Float32, 3> ijk_bbox(
222 mi::math::Vector<mi::Float32, 3 >(0.0f),
223 mi::math::Vector<mi::Float32, 3 >(static_cast<mi::Float32>(volume_size.x),
224 static_cast<mi::Float32>(volume_size.y),
225 static_cast<mi::Float32>(volume_size.z)));
226
227 mi::base::Handle<nv::index::ISparse_volume_scene_element> sparse_volume(
228 scene_edit->create_sparse_volume(ijk_bbox, transform_mat, generator, dice_transaction.get()));
229 check_success(sparse_volume.is_valid_interface());
230 sparse_volume->set_enabled(true);
231
232
233 // ... and store the volume scene element in the distributed database ...
234 sparse_volume_tag = dice_transaction->store_for_reference_counting(sparse_volume.get());
235 check_success(sparse_volume_tag.is_valid());
236
237 static_group->append(sparse_volume_tag, dice_transaction.get());
238 mi::neuraylib::Tag static_group_tag = dice_transaction->store_for_reference_counting(static_group.get());
239 check_success(static_group_tag.is_valid());
240
241 // append the static scene group to the hierarchical scene description.
242 scene_edit->append(static_group_tag, dice_transaction.get());
243
244 std::stringstream sstr;
245 sstr << "Created a synthetic volume: size = ["
246 << volume_size.x << " " << volume_size.y << " " << volume_size.z
247 << "], tag = " << sparse_volume_tag.id;
248 INFO_LOG << sstr.str();
249
250 // Create a camera and adjust the camera parameter.
251 mi::base::Handle< nv::index::IPerspective_camera > cam(
252 scene_edit->create_camera<nv::index::IPerspective_camera>());
253 check_success(cam.is_valid_interface());
254 setup_camera(cam.get());
255 const mi::neuraylib::Tag camera_tag = dice_transaction->store(cam.get());
256 check_success(camera_tag.is_valid());
257 // ... and add the camera to the scene.
258 scene_edit->set_camera(camera_tag);
259
260 const mi::math::Vector<mi::Uint32, 2> buffer_resolution(1024, 1024);
261 m_image_file_canvas->set_resolution(buffer_resolution);
262
263 // Define a region of interest for the entire scene in the
264 // scene's global coordinate system.
265 const mi::math::Bbox_struct<mi::Float32, 3> region_of_interest =
266 {
267 { 0.0f, 0.0f, 0.0f, },
268 {
269 static_cast< mi::Float32 >(volume_size.x),
270 static_cast< mi::Float32 >(volume_size.y),
271 static_cast< mi::Float32 >(volume_size.z),
272 },
273 };
274 scene_edit->set_clipped_bounding_box(region_of_interest);
275
276 // Finally, optionally adjust the scene's coordinate system
277 mi::math::Matrix<mi::Float32, 4, 4> transform(
278 1.0f, 0.0f, 0.0f, 0.0f,
279 0.0f, 1.0f, 0.0f, 0.0f,
280 0.0f, 0.0f, -1.0f, 0.0f, // adjust for coordinate system
281 0.0f, 0.0f, 0.0f, 1.0f
282 );
283 scene_edit->set_transform_matrix(transform);
284 }
285 }
286 dice_transaction->commit();
287 }
288
289 // Render the initial scene
290 {
291 // Render a frame and save the rendered image to a file.
292 const mi::Sint32 frame_idx = 0;
293 const std::string fname = get_output_file_name(m_outfname, frame_idx);
294
295 mi::base::Handle<nv::index::IFrame_results> frame_results(render_frame(fname));
296 const mi::base::Handle<nv::index::IError_set> err_set(frame_results->get_error_set());
297 if (err_set->any_errors())
298 {
299 std::ostringstream os;
300 const mi::Uint32 nb_err = err_set->get_nb_errors();
301 for (mi::Uint32 e = 0; e < nb_err; ++e)
302 {
303 if (e != 0) os << '\n';
304 const mi::base::Handle<nv::index::IError> err(err_set->get_error(e));
305 os << err->get_error_string();
306 }
307
308 ERROR_LOG << "IIndex_rendering rendering call failed with the following error(s): " << '\n'
309 << os.str();
310 exit_code = 1;
311 }
312
313 // verify the generated frame
314 if (!verify_canvas_result(get_application_layer_interface(),
315 m_image_file_canvas.get(), m_verify_image_fname, get_options()))
316 {
317 exit_code = 1;
318 }
319 }
320
321 // --------- EDITING THE VOLUME ------------
322 {
323 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
324 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
325 check_success(dice_transaction.is_valid_interface());
326 {
327 edit_volume_data(sparse_volume_tag, m_session_tag, dice_transaction.get());
328 }
329 dice_transaction->commit();
330 }
331
332 // Render the edited scene
333 {
334 // Render a frame and save the rendered image to a file.
335 const mi::Sint32 frame_idx = 0;
336 const std::string fname = "edited_" + get_output_file_name(m_outfname, frame_idx);
337 mi::base::Handle<nv::index::IFrame_results> frame_results(render_frame(fname));
338
339 const mi::base::Handle<nv::index::IError_set> err_set(frame_results->get_error_set());
340 if (err_set->any_errors())
341 {
342 std::ostringstream os;
343
344 const mi::Uint32 nb_err = err_set->get_nb_errors();
345 for (mi::Uint32 e = 0; e < nb_err; ++e)
346 {
347 if (e != 0) os << '\n';
348 const mi::base::Handle<nv::index::IError> err(err_set->get_error(e));
349 os << err->get_error_string();
350 }
351
352 ERROR_LOG << "NVIDIA IndeX rendering call failed with the following error(s): " << '\n'
353 << os.str();
354 }
355
356 // verify the generated frame
357 if (!verify_canvas_result(get_application_layer_interface(),
358 m_image_file_canvas.get(), m_verify_image_fname_second, get_options()))
359 {
360 exit_code = 1;
361 }
362 }
363 }
364
365 return exit_code;
366}
367
368//----------------------------------------------------------------------
369bool Parallel_volume_editing::evaluate_options(nv::index::app::String_dict& sdict)
370{
371 const std::string com_name = sdict.get("command:", "<unknown_command>");
372 m_is_unittest = nv::index::app::get_bool(sdict.get("unittest", "false"));
373
374 if (m_is_unittest)
375 {
376 if (nv::index::app::get_bool(sdict.get("is_call_from_test", "false")))
377 {
378 sdict.insert("is_dump_comparison_image_when_failed", "0");
379 }
380 sdict.insert("outfname", ""); // turn off file output in the unit test mode
381 sdict.insert("dice::verbose", "2");
382 const std::string vimage_base1 = sdict.get("unittest_verify_image_fbase");
383 const std::string vimage_base2 = sdict.get("unittest_verify_image_fbase_second");
384 if(!vimage_base1.empty())
385 {
386 sdict.get("verify_image_fname") = vimage_base1 + ".ppm";
387 }
388 if(!vimage_base2.empty())
389 {
390 sdict.get("verify_image_fname_second") = vimage_base2 + ".ppm";
391 }
392 }
393
394 m_outfname = sdict.get("outfname");
395 m_verify_image_fname = sdict.get("verify_image_fname");
396 m_verify_image_fname_second = sdict.get("verify_image_fname_second");
397 m_perlin_noise = nv::index::app::get_bool(sdict.get("perlin_noise", "false"));
398 m_unittest_verify_image_fbase = sdict.get("unittest_verify_image_fbase");
399 m_unittest_verify_image_fbase_second = sdict.get("unittest_verify_image_fbase_second");
400
401 info_cout(std::string("running ") + com_name, sdict);
402 info_cout("outfname = [" + m_outfname +
403 "], verify_image_fname = [" + m_verify_image_fname +
404 "], verify_image_fname_second = [" + m_verify_image_fname_second +
405 "], dice::verbose = " + sdict.get("dice::verbose"), sdict);
406
407 // print help and exit if -h
408 if (sdict.is_defined("h"))
409 {
410 std::cout
411 << "info: Usage: " << com_name << " [option]\n"
412 << "Option: [-h]\n"
413 << " print out this message\n"
414
415 << " [-dice::verbose severity_level INT]\n"
416 << " verbose severity level by INT (3 is info).\n"
417 << " (default: " + sdict.get("dice::verbose") << ")\n"
418
419 << " [-perlin_noise BOOL]\n"
420 << " when true, use Perlin noise to generate the volume, instead of\n"
421 << " a simpler color scheme. Note that this can be computationally expensive.\n"
422 << " (default: [" << m_perlin_noise << "])\n"
423
424 << " [-outfname FILE_BASENAME]\n"
425 << " output ppm file base name. When empty, no output.\n"
426 << " A frame number and extension (.ppm) will be added.\n"
427 << " (default: [" << m_outfname << "])\n"
428
429 << " [-verify_image_fname REF_IMAGE_FILENAME]\n"
430 << " when REF_IMAGE_FILENAME exist, verify the first rendered image.\n"
431 << " (default: [" << m_verify_image_fname << "])\n"
432
433 << " [-verify_image_fname_second REF_IMAGE_FILENAME]\n"
434 << " when REF_IMAGE_FILENAME exist, verify the second rendered image.\n"
435 << " (default: [" << m_verify_image_fname_second << "])\n"
436
437 << " [-unittest BOOL]\n"
438 << " when true, unit test mode. \n"
439 << " (default: [" << m_is_unittest << "])"
440
441 << " [-unittest_verify_image_fbase REF_IMAGE_FILENAME]\n"
442 << " when REF_IMAGE_FILENAME exist, verify the first rendered image.\n"
443 << " Only effective with -unittest 1.\n"
444 << " (default: [" << m_unittest_verify_image_fbase << "])\n"
445
446 << " [-unittest_verify_image_fbase_second REF_IMAGE_FILENAME]\n"
447 << " when REF_IMAGE_FILENAME exist, verify the second rendered image.\n"
448 << " Only effective with -unittest 1.\n"
449 << " (default: [" << m_unittest_verify_image_fbase_second << "])\n"
450
451 << std::endl;
452 exit(1);
453 }
454 return true;
455}
456
457//----------------------------------------------------------------------
458mi::math::Color_struct Parallel_volume_editing::jetmap(mi::Float32 v, mi::Float32 vmin, mi::Float32 vmax) const
459{
460 mi::math::Color_struct c = {1.f, 1.f, 1.f, 0.01f};
461 mi::Float32 dv;
462
463 if (v < vmin)
464 v = vmin;
465 if (v > vmax)
466 v = vmax;
467 dv = vmax - vmin;
468
469 if (v < (vmin + 0.25f * dv))
470 {
471 c.r = 0.f;
472 c.g = 4.f * (v - vmin) / dv;
473 }
474 else if (v < (vmin + 0.5f * dv))
475 {
476 c.r = 0.f;
477 c.b = 1.f + 4.f * (vmin + 0.25f * dv - v) / dv;
478 }
479 else if (v < (vmin + 0.75f * dv))
480 {
481 c.r = 4.f * (v - vmin - 0.5f * dv) / dv;
482 c.b = 0.f;
483 }
484 else
485 {
486 c.g = 1.f + 4.f * (vmin + 0.75f * dv - v) / dv;
487 c.b = 0.f;
488 }
489
490 return(c);
491}
492
493//----------------------------------------------------------------------
494nv::index::IColormap* Parallel_volume_editing::create_colormap(nv::index::IScene* scene) const
495{
496 nv::index::IColormap* colormap = scene->create_attribute<nv::index::IColormap>();
497 check_success(colormap != 0);
498 std::vector<mi::math::Color_struct> colormap_entries;
499 colormap_entries.resize(256);
500 for(mi::Uint32 i=0; i<256; ++i)
501 {
502 colormap_entries[i] = jetmap((static_cast<mi::Float32>(i)+0.5f)/256.0f, 0.0f, 1.0f);
503 }
504
505 // Set the the colormap values.
506 colormap->set_colormap(&colormap_entries[0], colormap_entries.size());
507 return colormap;
508}
509
510//----------------------------------------------------------------------
511void Parallel_volume_editing::edit_volume_data(
512 mi::neuraylib::Tag sparse_volume_tag,
513 mi::neuraylib::Tag session_tag,
514 mi::neuraylib::IDice_transaction* dice_transaction) const
515{
516 // Access the session
517 mi::base::Handle<const nv::index::ISession> session(
518 dice_transaction->access<nv::index::ISession>(session_tag));
519 check_success(session.is_valid_interface());
520
521 // Access to the sparse volume scene element
522 mi::base::Handle<const nv::index::ISparse_volume_scene_element> sparse_volume(
523 dice_transaction->access<nv::index::ISparse_volume_scene_element>(sparse_volume_tag));
524 check_success(sparse_volume.is_valid_interface());
525 const mi::math::Bbox<mi::Float32, 3> query_bbox_f32 = sparse_volume->get_bounding_box();
526
527 // Access the distribution scheme
528 const mi::neuraylib::Tag dist_layout_tag = session->get_distribution_layout();
529 check_success(dist_layout_tag.is_valid());
530 mi::base::Handle<const nv::index::IData_distribution> distribution_layout(
531 dice_transaction->access<nv::index::IData_distribution>(dist_layout_tag));
532 check_success(distribution_layout.is_valid_interface());
533
534 const mi::math::Bbox<mi::Sint32, 3> query_bbox_s32(query_bbox_f32);
535 mi::base::Handle<nv::index::IDistributed_data_locality> svol_data_locality(
536 distribution_layout->get_data_locality<nv::index::ISparse_volume_scene_element>(sparse_volume_tag, query_bbox_f32, dice_transaction));
537 check_success(svol_data_locality.is_valid_interface());
538
539 // Determine the host ids of all hosts in the cluster which store parts of the volume data
540 for (mi::Uint32 i=0; i < svol_data_locality->get_nb_cluster_nodes(); ++i)
541 {
542 // Host id 0 specifies that this subregion has not yet been loaded.
543 // This should not happen.
544 check_success(svol_data_locality->get_cluster_node(i) != 0);
545 const mi::Uint32 host_id = svol_data_locality->get_cluster_node(i);
546 INFO_LOG << "Cluster host "
547 << svol_data_locality->get_cluster_node(i)
548 << " is responsible for processing "
549 << svol_data_locality->get_nb_bounding_box(host_id)
550 << " problems.";
551 }
552
553 // Set up distributed editing process.
554 const mi::Float64 start_time = nv::index::app::util::time::get_time();
555 const mi::Uint8 voxel_value = 255;
556 // Access an application layer component that provides some sample distributed jobs:
557 mi::base::Handle<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing> processing(
558 get_application_layer_interface()->get_api_component<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing>());
559 check_success(processing.is_valid_interface());
560 // Create a job that distributed to all nodes/GPUs and add edits the volume data.
561 // For more details on how to implement the mandelbrot, please review the provided
562 // source that was shipped with the application layer component 'nv::index::app::data_analysis_and_processing::IData_analysis_and_processing'.
563 mi::base::Handle<nv::index::IDistributed_data_job> algo(processing->get_sample_tool_set()->create_sparse_volume_voxel_value_setting(
564 sparse_volume_tag,
565 voxel_value,
566 query_bbox_s32));
567 check_success(algo.is_valid_interface());
568 // Start the fragmented job
569 distribution_layout->create_scheduler()->execute(algo.get(), dice_transaction);
570
571 // Performance measurements
572 const mi::Float64 end_time = nv::index::app::util::time::get_time();
573 const mi::Float64 elapsed_time = end_time - start_time;
574 INFO_LOG << "Total elapsed time for volume edit: " << elapsed_time;
575}
576
577//----------------------------------------------------------------------
578void Parallel_volume_editing::setup_camera(nv::index::IPerspective_camera* cam) const
579{
580 check_success(cam != 0);
581
582 // Set the camera parameters to see the whole scene
583 const mi::math::Vector< mi::Float32, 3 > from(2048.f, 1536.f,-756.f);
584 const mi::math::Vector< mi::Float32, 3 > to ( 512.f, 512.2f,-512.7f);
585 const mi::math::Vector< mi::Float32, 3 > up ( 0.f, 0.f, -1.f);
586 mi::math::Vector<mi::Float32, 3> viewdir = to - from;
587 viewdir.normalize();
588
589 cam->set(from, viewdir, up);
590 cam->set_aperture(0.033f);
591 cam->set_aspect(1.0f);
592 cam->set_focal(0.03f);
593 cam->set_clip_min(2.0f);
594 cam->set_clip_max(400.0f);
595}
596
597//----------------------------------------------------------------------
598nv::index::IFrame_results* Parallel_volume_editing::render_frame(const std::string& output_fname) const
599{
600 check_success(m_index_rendering.is_valid_interface());
601
602 // set output filename, empty string is valid
603 m_image_file_canvas->set_rgba_file_name(output_fname.c_str());
604
605 check_success(m_session_tag.is_valid());
606
607 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
608 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
609 check_success(dice_transaction.is_valid_interface());
610
611 m_index_session->update(m_session_tag, dice_transaction.get());
612
613 mi::base::Handle<nv::index::IFrame_results> frame_results(
614 m_index_rendering->render(
615 m_session_tag,
616 m_image_file_canvas.get(),
617 dice_transaction.get()));
618 check_success(frame_results.is_valid_interface());
619
620 dice_transaction->commit();
621
622 frame_results->retain();
623 return frame_results.get();
624}
625
626//----------------------------------------------------------------------
627// This example shows how to edit a sparse volume in parallel.
628int main(int argc, const char* argv[])
629{
630 nv::index::app::String_dict sdict;
631 sdict.insert("dice::verbose", "3"); // log level
632 sdict.insert("dice::network::multicast_address", ""); // default multicast address. empty means network is disabled.
633 sdict.insert("dice::network::cluster_interface", ""); // default cluster interface address
634 sdict.insert("perlin_noise", "0");
635
636 sdict.insert("outfname", "frame_parallel_volume_editing"); // output file base name
637 sdict.insert("verify_image_fname", ""); //
638 sdict.insert("verify_image_fname_second", "");
639 sdict.insert("unittest_verify_image_fbase", ""); // for unit test
640 sdict.insert("unittest_verify_image_fbase_second", ""); // for unit test
641 sdict.insert("unittest", "0"); // default mode
642 sdict.insert("is_dump_comparison_image_when_failed", "1"); // default: dump images when failed.
643 sdict.insert("is_call_from_test", "0"); // default: not call from make check.
644
645 // DiCE settings
646 sdict.insert("dice::network::mode", "OFF");
647
648 // IndeX settings
649 sdict.insert("index::config::set_monitor_performance_values", "true");
650 sdict.insert("index::service", "rendering_and_compositing");
651 sdict.insert("index::cuda_debug_checks", "false");
652
653 // Application_layer settings
654 sdict.insert("index::app::components::application_layer::component_name_list",
655 "canvas_infrastructure image io data_analysis_and_processing");
656 // plugin: base_importer
657 sdict.insert("index::app::plugins::base_importer::enabled", "true");
658
659 // Initialize application
660 Parallel_volume_editing parallel_volume_editing;
661 parallel_volume_editing.initialize(argc, argv, sdict);
662 check_success(parallel_volume_editing.is_initialized());
663
664 // launch the application. creating the scene and rendering.
665 const mi::Sint32 exit_code = parallel_volume_editing.launch();
666 INFO_LOG << "Shutting down ...";
667
668 return exit_code;
669}
virtual bool initialize_networking(mi::neuraylib::INetwork_configuration *network_configuration, nv::index::app::String_dict &options) CPP11_OVERRIDE
virtual bool evaluate_options(nv::index::app::String_dict &sdict) CPP11_OVERRIDE
int main(int argc, const char *argv[])
#define check_success(expr)