NVIDIA Index example code nvidia_logo_transpbg.gif Up
dynamic_plane.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/iindex.h>
14#include <nv/index/ilight.h>
15#include <nv/index/imaterial.h>
16#include <nv/index/iscene.h>
17#include <nv/index/iscene_group.h>
18#include <nv/index/isession.h>
19#include <nv/index/iplane.h>
20#include <nv/index/itexture_filter_mode.h>
21
22#include "utility/canvas_utility.h"
23
24#include <nv/index/app/idata_analysis_and_processing.h>
25#include <nv/index/app/index_connect.h>
26#include <nv/index/app/string_dict.h>
27#include <nv/index/app/time_functions.h>
28
29#include <iostream>
30#include <sstream>
31
32//----------------------------------------------------------------------
34 public nv::index::app::Index_connect
35{
36public:
38 :
39 Index_connect(),
40 m_is_unittest(false),
41 m_max_iter(0)
42 {
43 // INFO_LOG << "DEBUG: Dynamic_plane() ctor";
44 }
45
47 {
48 // Note: Index_connect::~Index_connect() will be called after here.
49 // INFO_LOG << "DEBUG: ~Dynamic_plane() dtor";
50 }
51
52 // launch application
53 mi::Sint32 launch();
54
55protected:
56 virtual bool evaluate_options(nv::index::app::String_dict& sdict) CPP11_OVERRIDE;
57 // override
59 mi::neuraylib::INetwork_configuration* network_configuration,
60 nv::index::app::String_dict& options) CPP11_OVERRIDE
61 {
62 check_success(network_configuration != 0);
63
64 check_success(options.is_defined("unittest"));
65 const bool is_unittest = nv::index::app::get_bool(options.get("unittest"));
66 if (is_unittest)
67 {
68 info_cout("NETWORK: disabled networking mode.", options);
69 network_configuration->set_mode(mi::neuraylib::INetwork_configuration::MODE_OFF);
70 return true;
71 }
72
73 return initialize_networking_as_default_udp(network_configuration, options);
74 }
75
76private:
77 // create plane instances
78 void create_planes(nv::index::IScene* scene_edit,
79 mi::neuraylib::IDice_transaction* dice_transaction);
80 // move planes
81 // \param[in] dice_transaction dice transaction
82 void move_planes(mi::neuraylib::IDice_transaction* dice_transaction) const;
83 // setup camera to see this example scene
84 // \param[in] cam a camera
85 void setup_camera(nv::index::IPerspective_camera* cam) const;
86 // render a frame
87 // \param[in] output_fname output rendering image filename
88 // \return performance values
89 nv::index::IFrame_results* render_frame(const std::string& output_fname) const;
90
91 // This session tag
92 mi::neuraylib::Tag m_session_tag;
93 // NVIDIA IndeX cluster configuration
94 mi::base::Handle<nv::index::ICluster_configuration> m_cluster_configuration;
95 // Application layer image file canvas (a render target)
96 mi::base::Handle<nv::index::app::canvas_infrastructure::IIndex_image_file_canvas> m_image_file_canvas;
97 // Create_icons options
98 std::string m_outfname;
99 bool m_is_unittest;
100 std::string m_verify_image_fname;
101 mi::Sint32 m_max_iter;
102 // plane tags
103 std::vector<mi::neuraylib::Tag> m_plane_tag_vec;
104};
105
106//----------------------------------------------------------------------
108{
109 mi::Sint32 exit_code = 0;
110
111 // Get DiCE database components
112 {
113 m_cluster_configuration =
114 get_index_interface()->get_api_component<nv::index::ICluster_configuration>();
115 check_success(m_cluster_configuration.is_valid_interface());
116
117 // create image canvas in application_layer
118 m_image_file_canvas = create_image_file_canvas(get_application_layer_interface());
119 check_success(m_image_file_canvas.is_valid_interface());
120
121 // Verifying that local host has joined
122 const mi::Sint32 max_retry = 3;
123 for (mi::Sint32 retry = 0; retry < max_retry; ++retry)
124 {
125 if (m_cluster_configuration->get_number_of_hosts() == 0)
126 {
127 INFO_LOG << "no host joined yet, retry "
128 << (retry + 1) << "/" << max_retry;
129 nv::index::app::util::time::sleep(0.3f);
130 }
131 }
132 check_success(m_cluster_configuration->get_number_of_hosts() != 0);
133
134 {
135 // Obtain a DiCE transaction
136 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
137 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
138 check_success(dice_transaction.is_valid_interface());
139 {
140 // Setup session information
141 m_session_tag =
142 m_index_session->create_session(dice_transaction.get());
143 check_success(m_session_tag.is_valid());
144
145 mi::base::Handle<const nv::index::ISession> session(
146 dice_transaction->access<nv::index::ISession>(
147 m_session_tag));
148 check_success(session.is_valid_interface());
149
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 //----------------------------------------------------------------------
155 // Scene setup: add textured planes
156 //----------------------------------------------------------------------
157 create_planes(scene_edit.get(), dice_transaction.get());
158
159 mi::base::Handle< nv::index::IPerspective_camera > cam(
160 scene_edit->create_camera<nv::index::IPerspective_camera>());
161 check_success(cam.is_valid_interface());
162 setup_camera(cam.get());
163 const mi::neuraylib::Tag camera_tag = dice_transaction->store(cam.get());
164 check_success(camera_tag.is_valid());
165
166 const mi::math::Vector<mi::Uint32, 2> buffer_resolution(512, 512);
167 m_image_file_canvas->set_resolution(buffer_resolution);
168
169 // Set up the scene and define the region of interest
170 const mi::math::Bbox_struct<mi::Float32, 3> xyz_roi_st = {
171 { -1000.0f, -1000.0f, -1000.0f, },
172 { 1000.0f, 1000.0f, 1000.0f, },
173 };
174
175 // scope for scene edit
176 {
177 mi::base::Handle< nv::index::IScene > scene(
178 dice_transaction->edit< nv::index::IScene >(session->get_scene()));
179 check_success(scene.is_valid_interface());
180
181 // set the region of interest
182 const mi::math::Bbox< mi::Float32, 3 > xyz_roi(xyz_roi_st);
183 check_success(xyz_roi.is_volume());
184 scene->set_clipped_bounding_box(xyz_roi_st);
185
186 // Set the scene global transformation matrix.
187 // only change the coordinate system
188 mi::math::Matrix<mi::Float32, 4, 4> transform_mat(
189 1.0f, 0.0f, 0.0f, 0.0f,
190 0.0f, 1.0f, 0.0f, 0.0f,
191 0.0f, 0.0f, -1.0f, 0.0f,
192 0.0f, 0.0f, 0.0f, 1.0f
193 );
194 scene->set_transform_matrix(transform_mat);
195
196 // Set the current camera to the scene.
197 check_success(camera_tag.is_valid());
198 scene->set_camera(camera_tag);
199 }
200 }
201 dice_transaction->commit();
202 }
203
204 check_success(m_max_iter > 0);
205
206 // Render as many frame as requested by the user
207 for (mi::Sint32 i = 0; i < m_max_iter; ++i)
208 {
209 // Render the frame to a file
210 const std::string fname = get_output_file_name(m_outfname, i);
211 mi::base::Handle<nv::index::IFrame_results> frame_results(render_frame(fname));
212 const mi::base::Handle<nv::index::IError_set> err_set(frame_results->get_error_set());
213 if (err_set->any_errors())
214 {
215 std::ostringstream os;
216 const mi::Uint32 nb_err = err_set->get_nb_errors();
217 for (mi::Uint32 e = 0; e < nb_err; ++e)
218 {
219 if (e != 0) os << '\n';
220 const mi::base::Handle<nv::index::IError> err(err_set->get_error(e));
221 os << err->get_error_string();
222 }
223
224 ERROR_LOG << "IIndex_rendering rendering call failed with the following error(s): " << '\n'
225 << os.str();
226 exit_code = 1;
227 break;
228 }
229
230 // verify the generated frame
231 if (!(verify_canvas_result(get_application_layer_interface(),
232 m_image_file_canvas.get(), m_verify_image_fname, get_options())))
233 {
234 exit_code = 1;
235 break;
236 }
237
238 // Move the plane a bit
239 {
240 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
241 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
242 check_success(dice_transaction.is_valid_interface());
243 {
244 move_planes(dice_transaction.get());
245 }
246 dice_transaction->commit();
247 }
248 }
249 }
250 return exit_code;
251}
252
253//----------------------------------------------------------------------
254bool Dynamic_plane::evaluate_options(nv::index::app::String_dict& sdict)
255{
256 const std::string com_name = sdict.get("command:", "<unknown_command>");
257 m_is_unittest = nv::index::app::get_bool(sdict.get("unittest", "false"));
258
259 if (m_is_unittest)
260 {
261 if (nv::index::app::get_bool(sdict.get("is_call_from_test", "false")))
262 {
263 sdict.insert("is_dump_comparison_image_when_failed", "0");
264 }
265 sdict.insert("outfname", ""); // turn off file output in the unit test mode
266 sdict.insert("dice::verbose", "2");
267 sdict.insert("max_iter", "1");
268 }
269
270 m_outfname = sdict.get("outfname");
271 m_max_iter = nv::index::app::get_sint32(sdict.get("max_iter"));
272
273 info_cout(std::string("running ") + com_name, sdict);
274 info_cout("outfname = [" + m_outfname +
275 "], max_iter = " + nv::index::app::to_string(m_max_iter) +
276 ", dice::verbose = " + sdict.get("dice::verbose"), sdict);
277
278 // print help and exit if -h
279 if (sdict.is_defined("h"))
280 {
281 std::cout
282 << "info: Usage: " << com_name << " [option]\n"
283 << "Option: [-h]\n"
284 << " printout this message\n"
285 << " [-dice::verbose severity_level]\n"
286 << " verbose severity level (3 is info.). (default: " + sdict.get("dice::verbose")
287 << ")\n"
288
289 << " [-max_iter number_of_iteration]\n"
290 << " set rendering loop iterations. (default: "
291 << m_max_iter << " frames)\n"
292
293 << " [-outfname string]\n"
294 << " output ppm file base name. When empty, no output.\n"
295 << " A frame number and extension (.ppm) will be added.\n"
296 << " (default: [" << m_outfname << "])\n"
297
298 << " [-verify_image_fname [image_fname]]\n"
299 << " when image_fname exist, verify the rendering image. (default: ["
300 << m_verify_image_fname << "])\n"
301
302 << " [-unittest bool]\n"
303 << " when true, unit test mode. "
304 << m_is_unittest << "])"
305 << std::endl;
306 exit(1);
307 }
308 return true;
309}
310
311//----------------------------------------------------------------------
312void Dynamic_plane::create_planes(
313 nv::index::IScene* scene_edit,
314 mi::neuraylib::IDice_transaction* dice_transaction)
315{
316 check_success(dice_transaction != 0);
317
318 // Add a scene group where the shapes should be added
319 mi::base::Handle<nv::index::ITransformed_scene_group> group_node(
320 scene_edit->create_scene_group<nv::index::ITransformed_scene_group>());
321 check_success(group_node.is_valid_interface());
322
323 // Add a light and a material
324 {
325 // Add a light
326 mi::base::Handle<nv::index::IDirectional_headlight> headlight(
327 scene_edit->create_attribute<nv::index::IDirectional_headlight>());
328 check_success(headlight.is_valid_interface());
329 const mi::math::Color_struct color_intensity = { 1.0f, 1.0f, 1.0f, 1.0f, };
330 headlight->set_intensity(color_intensity);
331 headlight->set_direction(mi::math::Vector<mi::Float32, 3>(1.0f, -1.0f, -1.0f));
332 const mi::neuraylib::Tag headlight_tag = dice_transaction->store_for_reference_counting(headlight.get());
333 check_success(headlight_tag.is_valid());
334 group_node->append(headlight_tag, dice_transaction);
335
336 // Add a fully ambient material for the planes, so that lighting doesn't matter
337 mi::base::Handle<nv::index::IPhong_gl> phong_1(
338 scene_edit->create_attribute<nv::index::IPhong_gl>());
339 check_success(phong_1.is_valid_interface());
340 phong_1->set_ambient(mi::math::Color(1.0f, 1.0f, 1.0f));
341 phong_1->set_diffuse(mi::math::Color(0.0f));
342 phong_1->set_specular(mi::math::Color(0.0f));
343
344 mi::neuraylib::Tag phong_1_tag = dice_transaction->store_for_reference_counting(phong_1.get());
345 check_success(phong_1_tag.is_valid());
346 group_node->append(phong_1_tag, dice_transaction);
347
348 check_success(m_plane_tag_vec.empty()); // planes have not yet been created
349 }
350
351 //
352 // Plane 1: RGBA mode, axis aligned, no filtering
353 //
354 {
355 // Place plane centered in the origin, normal pointing along the z-axis
356 mi::math::Vector<mi::Float32, 3> plane_point(-400.f, -250.f, 0.0f);
357 mi::math::Vector<mi::Float32, 3> plane_normal(0.f, 0.f, 1.f);
358 mi::math::Vector<mi::Float32, 3> plane_up(0.f, 1.f, 0.f);
359 mi::math::Vector<mi::Float32, 2> plane_extent(800.0f, 500.0f);
360
361 mi::base::Handle<nv::index::ITexture_filter_mode> tex_filter(
362 scene_edit->create_attribute<nv::index::ITexture_filter_mode_nearest_neighbor>());
363 check_success(tex_filter.is_valid_interface());
364 mi::neuraylib::Tag tex_filter_tag = dice_transaction->store_for_reference_counting(tex_filter.get());
365 check_success(tex_filter_tag.is_valid());
366 group_node->append(tex_filter_tag, dice_transaction);
367
368 // Access an application layer component that provides some sample techniques such as the mandelbrot for 2d surfaces:
369 mi::base::Handle<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing> processing(
370 get_application_layer_interface()->get_api_component<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing>());
371 check_success(processing.is_valid_interface());
372 // Create a mandelbrot technique and add it to the scene. For more details on how to implement the mandelbrot, please review the provided
373 // source that was shipped with the application layer component 'nv::index::app::data_analysis_and_processing::IData_analysis_and_processing'.
374 mi::base::Handle<nv::index::IDistributed_compute_technique> mapping(
375 processing->get_sample_tool_set()->create_mandelbrot_2d_technique(
376 plane_extent, nv::index::IDistributed_compute_destination_buffer_2d_texture::FORMAT_RGBA_FLOAT32));
377 check_success(mapping.is_valid_interface());
378 mi::neuraylib::Tag mapping_tag = dice_transaction->store_for_reference_counting(mapping.get());
379 check_success(mapping_tag.is_valid());
380 group_node->append(mapping_tag, dice_transaction);
381
382 mi::base::Handle<nv::index::IPlane> plane(
383 scene_edit->create_shape<nv::index::IPlane>());
384 check_success(plane.is_valid_interface());
385 plane->set_point(plane_point);
386 plane->set_normal(plane_normal);
387 plane->set_up(plane_up);
388 plane->set_extent(plane_extent);
389
390 const mi::neuraylib::Tag plane_tag = dice_transaction->store_for_reference_counting(plane.get());
391 check_success(plane_tag.is_valid());
392 m_plane_tag_vec.push_back(plane_tag);
393
394 group_node->append(plane_tag, dice_transaction);
395 }
396
397 //
398 // Plane 2: Color map mode, arbitrary orientation, use texture filtering
399 //
400 {
401 mi::math::Vector<mi::Float32, 3> plane_point(-50.0f, 50.0f, 700.0f);
402 mi::math::Vector<mi::Float32, 3> plane_normal(1.f, 1.f, 1.f);
403 mi::math::Vector<mi::Float32, 3> plane_up(-1.f, 1.f, 0.f);
404 mi::math::Vector<mi::Float32, 2> plane_extent(400.0f, 400.0f);
405
406 const bool enable_texture_filtering = true;
407 const mi::Sint32 colormap_entry_id = 40; // same as demo application's colormap file 40
408 mi::neuraylib::Tag colormap_tag =
409 create_colormap(colormap_entry_id, scene_edit, dice_transaction);
410 check_success(colormap_tag.is_valid());
411 group_node->append(colormap_tag, dice_transaction);
412
413 mi::base::Handle<nv::index::ITexture_filter_mode> tex_filter;
414
415 if (enable_texture_filtering)
416 {
417 tex_filter = scene_edit->create_attribute<nv::index::ITexture_filter_mode_linear>();
418 }
419 else
420 {
421 tex_filter = scene_edit->create_attribute<nv::index::ITexture_filter_mode_nearest_neighbor>();
422 }
423 check_success(tex_filter.is_valid_interface());
424 mi::neuraylib::Tag tex_filter_tag = dice_transaction->store_for_reference_counting(tex_filter.get());
425 check_success(tex_filter_tag.is_valid());
426 group_node->append(tex_filter_tag, dice_transaction);
427
428 // Access an application layer component that provides some sample techniques such as the mandelbrot for 2d surfaces:
429 mi::base::Handle<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing> processing(
430 get_application_layer_interface()->get_api_component<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing>());
431 check_success(processing.is_valid_interface());
432 // Create a mandelbrot technique and add it to the scene. For more details on how to implement the mandelbrot, please review the provided
433 // source that was shipped with the application layer component 'nv::index::app::data_analysis_and_processing::IData_analysis_and_processing'.
434 mi::base::Handle<nv::index::IDistributed_compute_technique> mapping(
435 processing->get_sample_tool_set()->create_mandelbrot_2d_technique(
436 plane_extent, nv::index::IDistributed_compute_destination_buffer_2d_texture::FORMAT_SCALAR_UINT8));
437 check_success(mapping.is_valid_interface());
438 mi::neuraylib::Tag mapping_tag = dice_transaction->store_for_reference_counting(mapping.get());
439 check_success(mapping_tag.is_valid());
440 group_node->append(mapping_tag, dice_transaction);
441
442 mi::base::Handle<nv::index::IPlane> plane(
443 scene_edit->create_shape<nv::index::IPlane>());
444 check_success(plane.is_valid_interface());
445 plane->set_point(plane_point);
446 plane->set_normal(plane_normal);
447 plane->set_up(plane_up);
448 plane->set_extent(plane_extent);
449
450 mi::neuraylib::Tag plane_tag = dice_transaction->store_for_reference_counting(plane.get());
451 check_success(plane_tag.is_valid());
452 m_plane_tag_vec.push_back(plane_tag);
453
454 group_node->append(plane_tag, dice_transaction);
455 }
456
457 // Finally append everything to the root of the hierachical scene description
458 mi::neuraylib::Tag group_tag = dice_transaction->store_for_reference_counting(group_node.get());
459 check_success(group_tag.is_valid());
460 scene_edit->append(group_tag, dice_transaction);
461}
462
463//----------------------------------------------------------------------
464void Dynamic_plane::move_planes(mi::neuraylib::IDice_transaction* dice_transaction) const
465{
466 check_success(!m_plane_tag_vec.empty());
467
468 for(mi::Size i = 0; i < m_plane_tag_vec.size(); ++i)
469 {
470 mi::base::Handle<nv::index::IPlane> plane(
471 dice_transaction->edit<nv::index::IPlane>(m_plane_tag_vec.at(i)));
472 check_success(plane.is_valid_interface());
473
474 // Retrieve plane point
475 mi::math::Vector<mi::Float32, 3> point = plane->get_point();
476 mi::math::Vector<mi::Float32, 3> normal = plane->get_normal();
477
478 // Move it a bit into the direction of its normal vector
479 point += normal * -5.f;
480
481 plane->set_point(point);
482 }
483}
484
485//----------------------------------------------------------------------
486void Dynamic_plane::setup_camera(nv::index::IPerspective_camera* cam) const
487{
488 check_success(cam != 0);
489
490 // Set the camera parameters to see the whole scene.
491 const mi::math::Vector<mi::Float32, 3> from(100.0f, 0.0f, -1000.0f);
492 const mi::math::Vector<mi::Float32, 3> to (0.0f, 250.0f, 0.0f);
493 const mi::math::Vector<mi::Float32, 3> up (0.0f, 1.0f, 0.0f);
494 mi::math::Vector<mi::Float32, 3> viewdir = to - from;
495 viewdir.normalize();
496
497 cam->set(from, viewdir, up);
498 cam->set_aperture(0.033f);
499 cam->set_aspect(1.0f);
500 cam->set_focal(0.03f);
501 cam->set_clip_min(80.0f);
502 cam->set_clip_max(5000.0f);
503}
504
505//----------------------------------------------------------------------
506nv::index::IFrame_results* Dynamic_plane::render_frame(const std::string& output_fname) const
507{
508 check_success(m_index_rendering.is_valid_interface());
509
510 // set output filename, empty string is valid
511 m_image_file_canvas->set_rgba_file_name(output_fname.c_str());
512
513 check_success(m_session_tag.is_valid());
514
515 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
516 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
517 check_success(dice_transaction.is_valid_interface());
518
519 m_index_session->update(m_session_tag, dice_transaction.get());
520
521 mi::base::Handle<nv::index::IFrame_results> frame_results(
522 m_index_rendering->render(
523 m_session_tag,
524 m_image_file_canvas.get(),
525 dice_transaction.get()));
526 check_success(frame_results.is_valid_interface());
527
528 dice_transaction->commit();
529
530 frame_results->retain();
531 return frame_results.get();
532}
533
534//----------------------------------------------------------------------
535// This example shows how to create a dynamic plane
536int main(int argc, const char* argv[])
537{
538 nv::index::app::String_dict sdict;
539 sdict.insert("dice::verbose", "3"); // log level
540 sdict.insert("max_iter", "20"); // default max rendering loop iterations
541 sdict.insert("outfname", "frame_dynamic_plane"); // output file base name
542 sdict.insert("verify_image_fname", ""); // for unit test
543 sdict.insert("unittest", "0"); // default mode
544 sdict.insert("is_dump_comparison_image_when_failed", "1"); // default: dump images when failed.
545 sdict.insert("is_call_from_test", "0"); // default: not call from make check.
546
547 // Load IndeX library via Index_connect
548 sdict.insert("dice::network::mode", "OFF");
549
550 // index setting
551 sdict.insert("index::config::set_monitor_performance_values", "true");
552 sdict.insert("index::service", "rendering_and_compositing");
553 sdict.insert("index::cuda_debug_checks", "false");
554
555 // application_layer component loading
556 sdict.insert("index::app::components::application_layer::component_name_list",
557 "canvas_infrastructure image io data_analysis_and_processing");
558
559 // Initialize application
560 Dynamic_plane dynamic_plane;
561 dynamic_plane.initialize(argc, argv, sdict);
562 check_success(dynamic_plane.is_initialized());
563
564 // launch the application. creating the scene and rendering.
565 const mi::Sint32 exit_code = dynamic_plane.launch();
566 INFO_LOG << "Shutting down ...";
567
568 return exit_code;
569}
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
mi::Sint32 launch()
virtual ~Dynamic_plane()
int main(int argc, const char *argv[])
#define check_success(expr)