NVIDIA Index example code nvidia_logo_transpbg.gif Up
multi_view_trimesh.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/iconfig_settings.h>
14#include <nv/index/ifont.h>
15#include <nv/index/ilabel.h>
16
17#include <nv/index/iindex.h>
18#include <nv/index/iindex_debug_configuration.h>
19#include <nv/index/ilight.h>
20#include <nv/index/imaterial.h>
21#include <nv/index/iscene.h>
22#include <nv/index/isession.h>
23#include <nv/index/itriangle_mesh_query_results.h>
24#include <nv/index/itriangle_mesh_scene_element.h>
25#include <nv/index/iviewport.h>
26
27#include <nv/index/app/index_connect.h>
28#include <nv/index/app/string_dict.h>
29
30#include "utility/app_rendering_context.h"
31#include "utility/canvas_utility.h"
32
33#include <sstream>
34#include <iostream>
35
36//----------------------------------------------------------------------
38 public nv::index::app::Index_connect
39{
40public:
42 :
43 Index_connect()
44 {
45 // INFO_LOG << "DEBUG: Multi_view_trimesh() ctor";
46 }
47
49 {
50 // Note: Index_connect::~Index_connect() will be called after here.
51 // INFO_LOG << "DEBUG: ~Multi_view_trimesh() dtor";
52 }
53
54 // launch application
55 mi::Sint32 launch();
56
57protected:
58 virtual bool evaluate_options(nv::index::app::String_dict& sdict) CPP11_OVERRIDE;
59 // override
61 mi::neuraylib::INetwork_configuration* network_configuration,
62 nv::index::app::String_dict& options) CPP11_OVERRIDE
63 {
64 check_success(network_configuration != 0);
65
66 check_success(options.is_defined("unittest"));
67 const bool is_unittest = nv::index::app::get_bool(options.get("unittest"));
68 if (is_unittest)
69 {
70 info_cout("NETWORK: disabled networking mode.", options);
71 network_configuration->set_mode(mi::neuraylib::INetwork_configuration::MODE_OFF);
72 return true;
73 }
74
75 return initialize_networking_as_default_udp(network_configuration, options);
76 }
77
78private:
79 // Setup camera to see this example scene
80 // \param[in] camera_tag camera tag
81 // \param[in] dice_transaction dice transaction
82 void setup_camera(
83 const mi::neuraylib::Tag& camera_tag,
84 mi::neuraylib::IDice_transaction* dice_transaction) const;
85 // Localize scene elements
86 void localize_scene_element() const;
87 // Filter enable viewport index list
88 // \return newly created filtered viewport list
89 nv::index::IViewport_list* filter_enabled_viewport_index_list();
90 // Render one frame
91 // \param[in] frame_idx current frame index
92 // \return true when success
93 bool render_one_frame(mi::Sint32 frame_idx);
94 // Create multiple viewports
95 //
96 // The viewport structure of this example
97 //
98 // +-----------------+-----------------+(511,511)
99 // | viewport 0 | viewport 1 |
100 // (0,256)| global scope | camera change |(511,256)
101 // +-----------------+-----------------+
102 // (0,255)| viewport 2 | viewport 3 |(511,255)
103 // | camera change | camera/color/ |
104 // | | opacity change |
105 // +-----------------+-----------------+
106 // (0,0) (255,0) (256,0) (511,0)
107 //
108 //
109 // \param[in,out] arc application rendering context. multiple views will be updated.
110 void create_views() const;
111 // Add a label
112 //
113 // \param[in] scene_edit the editable IndeX scene
114 // \param[in] group_node parent group node
115 // \param[in] label_point label's corner position in the object space
116 // \param[in] label_str label contents string
117 // \param[in] label_height label height in the object space
118 // \param[in] label_width label width in the object space
119 // \param[in] fg_col label foreground color
120 // \param[in] bg_col label background color
121 // \param[in] dice_transaction db transaction
122 // \return created label tag
123 mi::neuraylib::Tag create_append_label_to_group(
124 nv::index::IScene* scene_edit,
125 nv::index::ITransformed_scene_group* group_node,
126 const mi::math::Vector<mi::Float32, 3>& label_point,
127 const std::string& label_str,
128 const mi::Float32 label_height,
129 const mi::Float32 label_width,
130 const mi::math::Color_struct& fg_col,
131 const mi::math::Color_struct& bg_col,
132 mi::neuraylib::IDice_transaction* dice_transaction);
133 // Set up the scene
134 // Create a scene that contains a triangle mesh.
135 // \param[in] dice_transaction db transaction
136 void setup_scene(mi::neuraylib::IDice_transaction* dice_transaction);
137 // Set up as the main host
138 // \return true when success
139 bool setup_main_host();
140
141 // This session tag
142 mi::neuraylib::Tag m_session_tag;
143 // NVIDIA IndeX cluster configuration
144 mi::base::Handle<nv::index::ICluster_configuration> m_cluster_configuration;
145 // Application layer image file canvas (a render target)
146 mi::base::Handle<nv::index::app::canvas_infrastructure::IIndex_image_file_canvas> m_image_file_canvas;
147 // Create_icons options
148 std::string m_outfname;
149 bool m_is_unittest;
150 std::string m_verify_image_path_base;
151 std::vector<bool> m_enable_view_idx_vec;
152 std::string m_font_fpath;
153 std::string m_iconfile;
154 std::string m_mesh_file;
155 mi::Float32 m_mesh_mat_opacity_0;
156 mi::Float32 m_mesh_mat_opacity_1;
157 std::string m_mesh_bbox;
158 mi::math::Bbox<mi::Float32, 3> m_roi;
159 // camera tag
160 mi::neuraylib::Tag m_camera_tag;
161 // trimesh scene element tag
162 mi::neuraylib::Tag m_trimesh_tag;
163 // triangle mesh material tag (phong)
164 mi::neuraylib::Tag m_mesh_phong_1_tag;
165 // static group node tag for trimesh
166 mi::neuraylib::Tag m_static_group_node_tag;
167 // label group node tag
168 mi::neuraylib::Tag m_label_group_node_tag;
169 // label tag vector
170 std::vector<mi::neuraylib::Tag> m_label_tag_vec;
171 mi::base::Handle<nv::index::IViewport_list> m_viewport_list;
172};
173
174//----------------------------------------------------------------------
176{
177 // setup
178 {
179 check_success(setup_main_host());
180
181 // Create multiple views in the arc.
182 create_views();
183
184 mi::Sint32 frame_idx = 0;
185 // Render multiple views for a single render call. Before localize.
186 {
187 // Render a frame and save the rendered image to a file.
188 const bool is_success = render_one_frame(frame_idx);
189 check_success(is_success);
190 ++frame_idx;
191 }
192
193 // localize scene elements
194 localize_scene_element();
195
196 // Render multiple views for a single render call.
197 {
198 // Render a frame and save the rendered image to a file.
199 const bool is_success = render_one_frame(frame_idx);
200 check_success(is_success);
201 ++frame_idx;
202 }
203 }
204 return 0;
205}
206
207//----------------------------------------------------------------------
208bool Multi_view_trimesh::evaluate_options(nv::index::app::String_dict& sdict)
209{
210 const std::string com_name = sdict.get("command:", "<unknown_command>");
211 m_is_unittest = nv::index::app::get_bool(sdict.get("unittest", "false"));
212 if (m_is_unittest)
213 {
214 sdict.insert("dice::verbose", "2");
215 }
216
217 m_outfname = sdict.get("outfname");
218 m_verify_image_path_base = sdict.get("verify_image_path_base");
219 m_enable_view_idx_vec = get_bool_vec_from_string(sdict.get("enable_vidx_vec"));
220 m_font_fpath = sdict.get("font_fpath");
221 m_iconfile = sdict.get("iconfile");
222 m_mesh_file = sdict.get("mesh_file");
223 m_mesh_mat_opacity_0 = nv::index::app::get_float32(sdict.get("mesh_mat_opacity_0"));
224 m_mesh_mat_opacity_1 = nv::index::app::get_float32(sdict.get("mesh_mat_opacity_1"));
225 m_mesh_bbox = sdict.get("mesh_bbox");
226 m_roi = nv::index::app::get_bbox_from_string<mi::Float32,3>(sdict.get("roi"));
227
228 info_cout("running " + com_name, sdict);
229 info_cout("outfname = [" + m_outfname +
230 "], verify_image_path_base = [" + m_verify_image_path_base +
231 "], dice::verbose = " + sdict.get("dice::verbose"), sdict);
232
233 // print help and exit if -h
234 if (sdict.is_defined("h"))
235 {
236 std::cout
237 << "info: Usage: " << com_name << " [option]\n"
238 << "Option: [-h]\n"
239 << " print out this message\n"
240
241 << " [-dice::verbose severity_level]\n"
242 << " verbose severity level (3 is info). (default: " + sdict.get("dice::verbose")
243 << ")\n"
244
245 << " [-font_fpath FONT_FILE_PATH]\n"
246 << " font file path. (default: " << m_font_fpath << ")\n"
247
248 << " [-mesh_file MESH_FILE_PATH]\n"
249 << " name of the triangle mesh file (in .bin-format). When empty, the default triangle mesh file will be used.\n"
250 << " (default: [" << m_mesh_file << "])\n"
251
252 << " [-mesh_mat_opacity_0 float]\n"
253 << " mesh material opacity 0."
254 << "(default: " << m_mesh_mat_opacity_0 << ")\n"
255
256 << " [-mesh_mat_opacity_1 float]\n"
257 << " mesh material opacity 1."
258 << "(default: " << m_mesh_mat_opacity_1 << ")\n"
259
260 << " [-mesh_bbox \"float float float float float float\"]\n"
261 << " mesh bounding box."
262 << "(default: " << m_mesh_bbox << ")\n"
263
264 << " [-roi \"float float float float float float\"]\n"
265 << " the bounding box representing the region of interest (roi).\n"
266 << " (default: [" << m_roi << "])\n"
267
268 << " [-outfname string]\n"
269 << " output ppm file base name. When empty, no output.\n"
270 << " A frame number and extension (.ppm) will be added.\n"
271 << " (default: [" << m_outfname << "])\n"
272
273 << " [-verify_image_path_base image path basename]\n"
274 << " when image_fname path basename exist, verify the rendering images.\n"
275 << " (default: [" << m_verify_image_path_base << "])\n"
276
277 << " [-unittest bool]\n"
278 << " when true, unit test mode. "
279 << "(default: [" << m_is_unittest << "])\n"
280
281 << " [-enable_vidx_vec enabled_vector]\n"
282 << " Specify which viewport is enabled by a bool vector.\n"
283 << " (default: [" << sdict.get("enable_vidx_vec") << "])"
284
285 << std::endl;
286 exit(1);
287 }
288 return true;
289}
290
291//----------------------------------------------------------------------
292void Multi_view_trimesh::setup_camera(
293 const mi::neuraylib::Tag& camera_tag,
294 mi::neuraylib::IDice_transaction* dice_transaction) const
295{
296 check_success(camera_tag.is_valid());
297
298 mi::base::Handle<nv::index::IPerspective_camera> cam(
299 dice_transaction->edit<nv::index::IPerspective_camera>(camera_tag));
300 check_success(cam.is_valid_interface());
301
302 // Set the camera parameters to see the whole scene
303 const mi::math::Vector<mi::Float32, 3> from( 450.0f, 800.0f, 1050.0f);
304 mi::math::Vector<mi::Float32, 3> dir ( 0.0f, 0.0f, -1.0f);
305 const mi::math::Vector<mi::Float32, 3> up ( 0.0f, 1.0f, 0.0f);
306 dir.normalize();
307
308 cam->set(from, dir, up);
309 cam->set_aperture(0.033f);
310 cam->set_aspect(1.0f);
311 cam->set_focal(0.03f);
312 cam->set_clip_min(2.0f);
313 cam->set_clip_max(1000.0f);
314}
315
316//----------------------------------------------------------------------
317void Multi_view_trimesh::localize_scene_element() const
318{
319 check_success(m_viewport_list.is_valid_interface());
320
321 // Process local viewports first.
322
323 // Set up viewport 1: enable the label 1 and change the camera
324 {
325 const mi::Size view_idx = 1;
326 check_success(m_viewport_list->size() > view_idx);
327
328 mi::base::Handle<nv::index::IViewport> viewport(m_viewport_list->get(view_idx));
329 check_success(viewport != 0);
330
331 mi::base::Handle<mi::neuraylib::IScope> cur_scope(viewport->get_scope());
332 check_success(cur_scope);
333 check_success(std::string(cur_scope->get_id()) == "1");
334
335 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
336 cur_scope->create_transaction<mi::neuraylib::IDice_transaction>());
337 check_success(dice_transaction.is_valid_interface());
338
339 // localize scene elements
340 {
341 // localize labels
342 for (mi::Size i = 0; i < m_label_tag_vec.size(); ++i)
343 {
344 mi::Sint32 ret_localize = 1;
345 ret_localize = dice_transaction->localize(m_label_tag_vec[i],
346 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
347 check_success(ret_localize == 0);
348 }
349
350 // localize camera
351 {
352 mi::Sint32 ret_localize = 1;
353 ret_localize = dice_transaction->localize(m_camera_tag,
354 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
355 check_success(ret_localize == 0);
356 }
357
358 // edit labels
359 for (mi::Size i = 0; i < m_label_tag_vec.size(); ++i)
360 {
361 mi::base::Handle<nv::index::ILabel_3D> label(
362 dice_transaction->edit<nv::index::ILabel_3D>(m_label_tag_vec[i]));
363 check_success(label.is_valid_interface());
364 if (i == view_idx)
365 {
366 label->set_enabled(true);
367 label->set_text("View 1: Left camera");
368 }
369 else
370 {
371 label->set_enabled(false);
372 }
373 }
374
375 // edit camera
376 {
377 mi::base::Handle<nv::index::ICamera> cam(
378 dice_transaction->edit<nv::index::ICamera>(m_camera_tag));
379 check_success(cam.is_valid_interface());
380
381 const mi::math::Vector<mi::Float32, 3> from( 100.0f, 800.0f, 1050.0f);
382 mi::math::Vector<mi::Float32, 3> dir ( 0.7f, 0.0f, -1.0f);
383 const mi::math::Vector<mi::Float32, 3> up ( 0.0f, 1.0f, 0.0f);
384 dir.normalize();
385
386 cam->set(from, dir, up);
387 }
388 }
389 dice_transaction->commit();
390 }
391
392 // Set up viewport 2: enable the label 2 and change the camera
393 {
394 const mi::Size view_idx = 2;
395 check_success(m_viewport_list->size() > view_idx);
396
397 mi::base::Handle<nv::index::IViewport> viewport(m_viewport_list->get(view_idx));
398 check_success(viewport != 0);
399
400 mi::base::Handle<mi::neuraylib::IScope> cur_scope(viewport->get_scope());
401 check_success(cur_scope);
402 check_success(std::string(cur_scope->get_id()) == "2");
403
404 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
405 cur_scope->create_transaction<mi::neuraylib::IDice_transaction>());
406 check_success(dice_transaction.is_valid_interface());
407
408 // localize scene elements
409 {
410 // localize labels
411 for (mi::Size i = 0; i < m_label_tag_vec.size(); ++i)
412 {
413 mi::Sint32 ret_localize = 1;
414 ret_localize = dice_transaction->localize(m_label_tag_vec[i],
415 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
416 check_success(ret_localize == 0);
417 }
418
419 // localize camera
420 {
421 mi::Sint32 ret_localize = 1;
422 ret_localize = dice_transaction->localize(m_camera_tag,
423 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
424 check_success(ret_localize == 0);
425 }
426
427 // edit labels
428 for (mi::Size i = 0; i < m_label_tag_vec.size(); ++i)
429 {
430 mi::base::Handle<nv::index::ILabel_3D> label(
431 dice_transaction->edit<nv::index::ILabel_3D>(m_label_tag_vec[i]));
432 check_success(label.is_valid_interface());
433 if (i == view_idx)
434 {
435 label->set_enabled(true);
436 label->set_text("View 2: right camera");
437 }
438 else
439 {
440 label->set_enabled(false);
441 }
442 }
443
444 // edit camera
445 {
446 mi::base::Handle<nv::index::ICamera> cam(
447 dice_transaction->edit<nv::index::ICamera>(m_camera_tag));
448 check_success(cam.is_valid_interface());
449
450 const mi::math::Vector<mi::Float32, 3> from( 800.0f, 800.0f, 1050.0f);
451 mi::math::Vector<mi::Float32, 3> dir ( -0.7f, 0.0f, -1.0f);
452 const mi::math::Vector<mi::Float32, 3> up ( 0.0f, 1.0f, 0.0f);
453 dir.normalize();
454
455 cam->set(from, dir, up);
456 }
457 }
458 dice_transaction->commit();
459 }
460
461 // Set up viewport 3: enable the label 3 and change the camera
462 {
463 const mi::Size view_idx = 3;
464 check_success(m_viewport_list->size() > view_idx);
465
466 mi::base::Handle<nv::index::IViewport> viewport(m_viewport_list->get(view_idx));
467 check_success(viewport != 0);
468
469 mi::base::Handle<mi::neuraylib::IScope> cur_scope(viewport->get_scope());
470 check_success(cur_scope);
471 check_success(std::string(cur_scope->get_id()) == "3");
472
473 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
474 cur_scope->create_transaction<mi::neuraylib::IDice_transaction>());
475 check_success(dice_transaction.is_valid_interface());
476
477 // localize scene elements
478 {
479 // localize labels
480 for (mi::Size i = 0; i < m_label_tag_vec.size(); ++i)
481 {
482 mi::Sint32 ret_localize = 1;
483 ret_localize = dice_transaction->localize(m_label_tag_vec[i],
484 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
485 check_success(ret_localize == 0);
486 }
487
488 // localize camera
489 {
490 mi::Sint32 ret_localize = 1;
491 ret_localize = dice_transaction->localize(m_camera_tag,
492 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
493 check_success(ret_localize == 0);
494 }
495
496 // localize material
497 {
498 check_success(m_mesh_phong_1_tag.is_valid());
499 mi::Sint32 ret_localize = 1;
500 ret_localize = dice_transaction->localize(m_mesh_phong_1_tag,
501 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
502 check_success(ret_localize == 0);
503 }
504
505 // edit labels
506 for (mi::Size i = 0; i < m_label_tag_vec.size(); ++i)
507 {
508 mi::base::Handle<nv::index::ILabel_3D> label(
509 dice_transaction->edit<nv::index::ILabel_3D>(m_label_tag_vec[i]));
510 check_success(label.is_valid_interface());
511 if (i == view_idx)
512 {
513 label->set_enabled(true);
514 label->set_text("zoom + green");
515 }
516 else
517 {
518 label->set_enabled(false);
519 }
520 }
521
522 // edit camera
523 {
524 mi::base::Handle<nv::index::ICamera> cam(
525 dice_transaction->edit<nv::index::ICamera>(m_camera_tag));
526 check_success(cam.is_valid_interface());
527
528 const mi::math::Vector<mi::Float32, 3> from( 450.0f, 800.0f, 900.0f);
529 mi::math::Vector<mi::Float32, 3> dir ( 0.0f, 0.0f, -1.0f);
530 const mi::math::Vector<mi::Float32, 3> up ( 0.0f, 1.0f, 0.0f);
531 dir.normalize();
532
533 cam->set(from, dir, up);
534 }
535
536 // edit material
537 {
538 mi::base::Handle<nv::index::IPhong_gl> phong_1(
539 dice_transaction->edit<nv::index::IPhong_gl>(m_mesh_phong_1_tag));
540 check_success(phong_1.is_valid_interface());
541 phong_1->set_opacity(m_mesh_mat_opacity_1);
542 phong_1->set_ambient( mi::math::Color(0.1f, 0.1f, 0.1f, m_mesh_mat_opacity_1));
543 phong_1->set_specular(mi::math::Color(0.4f, 0.4f, 0.75f, m_mesh_mat_opacity_1));
544 phong_1->set_diffuse( mi::math::Color(0.1f, 0.8f, 0.1f, m_mesh_mat_opacity_1));
545 }
546 }
547 dice_transaction->commit();
548 }
549
550 // Set up viewport 0 with the global scope: disable labels
551 {
552 const mi::Size view_idx = 0;
553 check_success(m_viewport_list->size() > view_idx);
554
555 mi::base::Handle<nv::index::IViewport> viewport(m_viewport_list->get(view_idx));
556 check_success(viewport != 0);
557
558 mi::base::Handle<mi::neuraylib::IScope> cur_scope(viewport->get_scope());
559 check_success(cur_scope);
560 check_success(std::string(cur_scope->get_id()) == "0");
561
562 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
563 cur_scope->create_transaction<mi::neuraylib::IDice_transaction>());
564 check_success(dice_transaction.is_valid_interface());
565
566 // edit scene elements
567 {
568 // edit labels
569 for (mi::Size i = 0; i < m_label_tag_vec.size(); ++i)
570 {
571 mi::base::Handle<nv::index::ILabel_3D> label(
572 dice_transaction->edit<nv::index::ILabel_3D>(m_label_tag_vec[i]));
573 check_success(label.is_valid_interface());
574
575 if (i == view_idx)
576 {
577 // label->set_text("View 0");
578 }
579 else
580 {
581 label->set_enabled(false);
582 }
583 }
584 }
585 dice_transaction->commit();
586 }
587}
588
589//----------------------------------------------------------------------
590nv::index::IViewport_list* Multi_view_trimesh::filter_enabled_viewport_index_list()
591{
592 mi::base::Handle<nv::index::IViewport_list> new_viewport_list;
593 {
594 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
595 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
596 assert(dice_transaction.is_valid_interface());
597 {
598 assert(m_session_tag.is_valid());
599 mi::base::Handle<const nv::index::ISession> session(
600 dice_transaction->access<nv::index::ISession>(m_session_tag));
601 assert(session.is_valid_interface());
602
603 // create viewport from a session
604 new_viewport_list = session->create_viewport_list();
605 }
606 dice_transaction->commit();
607 }
608
609 check_success(new_viewport_list.is_valid_interface());
610 const mi::Size nb_views = m_viewport_list->size();
611
612 std::stringstream sstr;
613 mi::Size nb_enabled = 0;
614 for (mi::Size i = 0; i < nb_views; ++i)
615 {
616 if (m_enable_view_idx_vec[i])
617 {
618 sstr << i << " ";
619 mi::base::Handle<nv::index::IViewport> vp (m_viewport_list->get(i));
620 new_viewport_list->append(vp.get());
621 ++nb_enabled;
622 }
623 }
624 // copy advisory state
625 new_viewport_list->set_advisory_enabled(m_viewport_list->get_advisory_enabled());
626
627 if (nb_enabled == nb_views)
628 {
629 INFO_LOG << "All views are enabled.";
630 }
631 else
632 {
633 INFO_LOG << "Filtered views. Enabled: " << sstr.str();
634 }
635
636 new_viewport_list->retain();
637 return new_viewport_list.get();
638}
639
640//----------------------------------------------------------------------
641bool Multi_view_trimesh::render_one_frame(mi::Sint32 frame_idx)
642{
643 bool success = true;
644
645 // Render a frame and save the rendered image to a file.
646 // Only save the file at the end of the iteration.
647 std::string fname = "";
648 if (!(m_outfname.empty()))
649 {
650 fname = get_output_file_name(m_outfname, frame_idx);
651 }
652 check_success(m_index_rendering.is_valid_interface());
653
654 // set up canvas. output_fname.empty() is valid (no output file)
655 m_image_file_canvas->set_rgba_file_name(fname.c_str());
656
657 // set advisory to see the multiview rendering details
658 m_viewport_list->set_advisory_enabled(true);
659
660 mi::base::Handle<nv::index::IViewport_list> cur_viewport_list(
661 filter_enabled_viewport_index_list());
662 check_success(cur_viewport_list.is_valid_interface());
663
664 mi::base::Handle<nv::index::IFrame_results_list> frame_results_list(
665 m_index_rendering->render(
666 m_session_tag,
667 m_image_file_canvas.get(),
668 cur_viewport_list.get()));
669 check_success(frame_results_list.is_valid_interface());
670
671 if (frame_results_list->size() == 0)
672 {
673 ERROR_LOG << "IIndex_rendering rendering call has no results.";
674 success = false;
675 }
676 else
677 {
678 for (mi::Size i = 0; i < frame_results_list->size(); ++i)
679 {
680 mi::base::Handle<nv::index::IFrame_results>
681 frame_results(frame_results_list->get(i));
682 check_success(frame_results.is_valid_interface());
683
684 const mi::base::Handle<nv::index::IError_set> err_set(frame_results->get_error_set());
685 check_success(err_set.is_valid_interface());
686 if (err_set->any_errors())
687 {
688 std::ostringstream os;
689
690 const mi::base::Handle<nv::index::IError_set> err_set(frame_results->get_error_set());
691 const mi::Uint32 nb_err = err_set->get_nb_errors();
692 for (mi::Uint32 e = 0; e < nb_err; ++e)
693 {
694 if (e != 0) os << '\n';
695 const mi::base::Handle<nv::index::IError> err(err_set->get_error(e));
696 os << err->get_error_string();
697 }
698
699 ERROR_LOG << "IIndex_rendering rendering call failed with the following error(s): " << '\n'
700 << os.str();
701 success = false;
702 }
703 }
704 }
705
706 // verify the generated frame
707 if (!(m_verify_image_path_base.empty()))
708 {
709 const std::string ref_img_fpath = get_output_file_name(m_verify_image_path_base, frame_idx);
710 if (!(verify_canvas_result(get_application_layer_interface(),
711 m_image_file_canvas.get(), ref_img_fpath, get_options())))
712 {
713 success = false;
714 }
715 }
716
717 return success;
718}
719
720//----------------------------------------------------------------------
721void Multi_view_trimesh::create_views() const
722{
723 // Check session and multiple views in the arc
724 check_success(m_session_tag.is_valid());
725 check_success(m_viewport_list.is_valid_interface());
726 check_success(m_viewport_list->size() == 0);
727
728 // Multiple viewport itself lives in the global scope.
729 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
730 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
731 check_success(dice_transaction.is_valid_interface());
732 {
733 mi::base::Handle<const nv::index::ISession> session(
734 dice_transaction->access<nv::index::ISession>(m_session_tag));
735 check_success(session.is_valid_interface());
736
737 // 0. create a single viewport in the global scope.
738 {
739 mi::base::Handle<nv::index::IViewport> viewport(session->create_viewport());
740 check_success(viewport.is_valid_interface());
741
742 const mi::math::Vector<mi::Sint32, 2> viewport_pos( 0, 256);
743 const mi::math::Vector<mi::Sint32, 2> viewport_size(256, 256);
744
745 viewport->set_position(viewport_pos);
746 viewport->set_size(viewport_size);
747 viewport->set_scope(m_global_scope.get()); // ref count up
748
749 m_viewport_list->append(viewport.get());
750 }
751
752 // 1. viewport
753 {
754 mi::base::Handle<nv::index::IViewport> viewport(session->create_viewport());
755 check_success(viewport.is_valid_interface());
756
757 mi::neuraylib::IScope* parent = 0; // this means global scope in this context
758 mi::Uint8 privacy_level = 1;
759 bool is_temp = false;
760 mi::base::Handle<mi::neuraylib::IScope> local_scope(m_database->create_scope(parent, privacy_level, is_temp));
761 check_success(local_scope.is_valid_interface());
762
763 const mi::math::Vector<mi::Sint32, 2> viewport_pos( 256, 256);
764 const mi::math::Vector<mi::Sint32, 2> viewport_size(256, 256);
765
766 viewport->set_position(viewport_pos);
767 viewport->set_size(viewport_size);
768 viewport->set_scope(local_scope.get()); // ref count up
769
770 m_viewport_list->append(viewport.get());
771 }
772
773 // 2. viewport
774 {
775 mi::base::Handle<nv::index::IViewport> viewport(session->create_viewport());
776 check_success(viewport.is_valid_interface());
777
778 mi::neuraylib::IScope* parent = 0; // this means global scope in this context
779 mi::Uint8 privacy_level = 1;
780 bool is_temp = false;
781 mi::base::Handle<mi::neuraylib::IScope> local_scope(m_database->create_scope(parent, privacy_level, is_temp));
782 check_success(local_scope.is_valid_interface());
783
784 const mi::math::Vector<mi::Sint32, 2> viewport_pos( 0, 0);
785 const mi::math::Vector<mi::Sint32, 2> viewport_size(256, 256);
786
787 viewport->set_position(viewport_pos);
788 viewport->set_size(viewport_size);
789 viewport->set_scope(local_scope.get()); // ref count up
790
791 m_viewport_list->append(viewport.get());
792 }
793
794 // 3. viewport
795 {
796 mi::base::Handle<nv::index::IViewport> viewport(session->create_viewport());
797 check_success(viewport.is_valid_interface());
798
799 mi::neuraylib::IScope* parent = 0; // this means global scope in this context
800 mi::Uint8 privacy_level = 1;
801 bool is_temp = false;
802 mi::base::Handle<mi::neuraylib::IScope> local_scope(m_database->create_scope(parent, privacy_level, is_temp));
803 check_success(local_scope.is_valid_interface());
804
805 const mi::math::Vector<mi::Sint32, 2> viewport_pos( 256, 0);
806 const mi::math::Vector<mi::Sint32, 2> viewport_size(256, 256);
807
808 viewport->set_position(viewport_pos);
809 viewport->set_size(viewport_size);
810 viewport->set_scope(local_scope.get()); // ref count up
811
812 m_viewport_list->append(viewport.get());
813 }
814 }
815 dice_transaction->commit();
816}
817
818
819//----------------------------------------------------------------------
820mi::neuraylib::Tag Multi_view_trimesh::create_append_label_to_group(
821 nv::index::IScene* scene_edit,
822 nv::index::ITransformed_scene_group* group_node,
823 const mi::math::Vector<mi::Float32, 3>& label_point,
824 const std::string& label_str,
825 const mi::Float32 label_height,
826 const mi::Float32 label_width,
827 const mi::math::Color_struct& fg_col,
828 const mi::math::Color_struct& bg_col,
829 mi::neuraylib::IDice_transaction* dice_transaction)
830{
831 check_success(scene_edit != 0);
832 check_success(group_node != 0);
833
834 // Add font to the scene description
835 mi::base::Handle<nv::index::IFont> font(scene_edit->create_attribute<nv::index::IFont>());
836 check_success(font.is_valid_interface());
837
838 if (font->set_file_name(m_font_fpath.c_str()))
839 {
840 INFO_LOG << "set the font path [" << m_font_fpath << "]";
841 }
842 else
843 {
844 ERROR_LOG << "Can not find the font path [" << m_font_fpath << "], "
845 << "the rendering result may not correct.";
846 }
847 font->set_font_resolution(64.0f);
848 const mi::neuraylib::Tag font_tag = dice_transaction->store_for_reference_counting(font.get());
849 INFO_LOG << "Created a font: tag: " << font_tag;
850 check_success(font_tag.is_valid());
851 group_node->append(font_tag, dice_transaction);
852
853 // Add a label
854 mi::neuraylib::Tag label_tag;
855 {
856 mi::base::Handle<nv::index::ILabel_layout> label_layout(
857 scene_edit->create_attribute<nv::index::ILabel_layout>());
858 check_success(label_layout.is_valid_interface());
859 const mi::Float32 padding = 20.0f;
860 label_layout->set_padding(padding);
861 label_layout->set_color(fg_col, bg_col);
862 const mi::neuraylib::Tag label_layout_tag =
863 dice_transaction->store_for_reference_counting(label_layout.get());
864 INFO_LOG << "Created a label_layout: tag: " << label_layout_tag;
865 check_success(label_layout_tag.is_valid());
866 group_node->append(label_layout_tag, dice_transaction);
867
868 mi::base::Handle<nv::index::ILabel_3D> label(scene_edit->create_shape<nv::index::ILabel_3D>());
869 check_success(label.is_valid_interface());
870 label->set_text(label_str.c_str());
871
872 const mi::math::Vector<mi::Float32, 3> right(1.0f, 0.0f, 0.0f);
873 const mi::math::Vector<mi::Float32, 3> up (0.0f, 1.0f, 0.0f);
874 label->set_geometry(label_point, right, up, label_height, label_width);
875 label_tag = dice_transaction->store_for_reference_counting(label.get());
876 INFO_LOG << "Created a label: tag: " << label_tag;
877 check_success(label_tag.is_valid());
878 group_node->append(label_tag, dice_transaction);
879 }
880 return label_tag;
881}
882
883//----------------------------------------------------------------------
884void Multi_view_trimesh::setup_scene(mi::neuraylib::IDice_transaction* dice_transaction)
885{
886 check_success(dice_transaction != 0);
887
888 // Access the session instance from the database.
889 mi::base::Handle<const nv::index::ISession> session(
890 dice_transaction->access<const nv::index::ISession>(m_session_tag));
891 check_success(session.is_valid_interface());
892
893 // Access (edit mode) the scene instance from the database.
894 mi::base::Handle<nv::index::IScene> scene_edit(
895 dice_transaction->edit<nv::index::IScene>(session->get_scene()));
896 check_success(scene_edit.is_valid_interface());
897
898 // Create static group node for large data
899 mi::base::Handle<nv::index::IStatic_scene_group> static_group_node(
900 scene_edit->create_scene_group<nv::index::IStatic_scene_group>());
901 check_success(static_group_node.is_valid_interface());
902
903 // Added a light and a material to the static group node for trimesh
904 {
905 // Add a light
906 mi::base::Handle<nv::index::IDirectional_headlight> headlight(
907 scene_edit->create_attribute<nv::index::IDirectional_headlight>());
908 check_success(headlight.is_valid_interface());
909 const mi::math::Color color_intensity(1.0f, 1.0f, 1.0f, 1.0f);
910 headlight->set_intensity(color_intensity);
911 headlight->set_direction(mi::math::Vector<mi::Float32, 3>(1.0f, -1.0f, -1.0f));
912
913 const mi::neuraylib::Tag headlight_tag = dice_transaction->store_for_reference_counting(headlight.get());
914 check_success(headlight_tag.is_valid());
915 static_group_node->append(headlight_tag, dice_transaction);
916 INFO_LOG << "Created a headlight: tag = " << headlight_tag.id;
917
918 // Material for the trimesh
919 mi::base::Handle<nv::index::IPhong_gl> phong_1(scene_edit->create_attribute<nv::index::IPhong_gl>());
920 check_success(phong_1.is_valid_interface());
921 phong_1->set_ambient(mi::math::Color(0.1f, 0.1f, 0.1f, 1.0f));
922 phong_1->set_diffuse(mi::math::Color(0.45f, 0.3f, 0.3f, 1.0f));
923 phong_1->set_specular(mi::math::Color(0.4f, 0.4f, 0.75f, 1.0f));
924 if (m_mesh_mat_opacity_0 < 0.99f)
925 {
926 INFO_LOG << "Material opacity is less than 1.0 (" << m_mesh_mat_opacity_0 << ")";
927 }
928 phong_1->set_opacity(m_mesh_mat_opacity_0);
929 phong_1->set_shininess(85);
930 check_success(!m_mesh_phong_1_tag.is_valid());
931 m_mesh_phong_1_tag = dice_transaction->store_for_reference_counting(phong_1.get());
932 check_success(m_mesh_phong_1_tag.is_valid());
933
934 scene_edit->append(m_mesh_phong_1_tag, dice_transaction);
935 static_group_node->append(m_mesh_phong_1_tag, dice_transaction);
936 INFO_LOG << "Created a phong material for the mesh: tag = " << m_mesh_phong_1_tag.id;
937 }
938
939 // Add a triangle mesh
940 {
941 // triangle mesh creation parameter
942 nv::index::app::String_dict triangle_mesh_opt;
943 triangle_mesh_opt.insert("args::type", "triangle_mesh");
944 triangle_mesh_opt.insert("args::importer", "nv::index::plugin::base_importer.Triangle_mesh_importer");
945 triangle_mesh_opt.insert("args::input_file", m_mesh_file);
946 triangle_mesh_opt.insert("args::bbox", m_mesh_bbox);
947 nv::index::IDistributed_data_import_callback* importer_callback =
948 get_importer_from_application_layer(
949 get_application_layer_interface(),
950 "nv::index::plugin::base_importer.Triangle_mesh_importer",
951 triangle_mesh_opt);
952
953 const mi::math::Bbox<mi::Float32, 3> mesh_bbox =
954 nv::index::app::get_bbox_from_string<mi::Float32,3>(m_mesh_bbox);
955 INFO_LOG << "mesh_file: " << m_mesh_file;
956 INFO_LOG << "mesh_bbox: " << mesh_bbox;
957
958 // Create the triangle mesh scene element
959 mi::base::Handle<nv::index::ITriangle_mesh_scene_element> mesh(
960 scene_edit->create_triangle_mesh(mesh_bbox, importer_callback, dice_transaction));
961 check_success(mesh != 0);
962
963 // scene element properties
964 mesh->set_enabled(true);
965
966 // storing the mesh in the data (base) store
967 m_trimesh_tag = dice_transaction->store_for_reference_counting(mesh.get());
968 check_success(m_trimesh_tag.is_valid());
969
970 // append mesh to the static scene group
971 static_group_node->append(m_trimesh_tag, dice_transaction);
972
973 m_static_group_node_tag = dice_transaction->store_for_reference_counting(static_group_node.get());
974 check_success(m_static_group_node_tag.is_valid());
975
976 // append the static scene group to the hierachical scene description.
977 scene_edit->append(m_static_group_node_tag, dice_transaction);
978 }
979
980 // Create and add labels
981 {
982 // Add a scene group where the shapes should be added
983 mi::base::Handle<nv::index::ITransformed_scene_group> label_group_node(
984 scene_edit->create_scene_group<nv::index::ITransformed_scene_group>());
985 check_success(label_group_node.is_valid_interface());
986
987 // Add a material
988 {
989 // Add a fully ambient material for the planes, so that lighting doesn't matter
990 mi::math::Color ambient_color (1.0f, 1.0f, 1.0f, 1.0f);
991 mi::math::Color diffuse_color (0.0f, 0.0f, 0.0f, 1.0f);
992 mi::math::Color specular_color(0.0f, 0.0f, 0.0f, 1.0f);
993 mi::Float32 shiness = 100.0f;
994 mi::base::Handle<nv::index::IPhong_gl> phong_1(
995 scene_edit->create_attribute<nv::index::IPhong_gl>());
996 check_success(phong_1.is_valid_interface());
997 phong_1->set_ambient(ambient_color);
998 phong_1->set_diffuse(diffuse_color);
999 phong_1->set_specular(specular_color);
1000 phong_1->set_shininess(shiness);
1001
1002 mi::neuraylib::Tag phong_1_tag = dice_transaction->store_for_reference_counting(phong_1.get());
1003 INFO_LOG << "Created phong for labels: tag: " << phong_1_tag;
1004 check_success(phong_1_tag.is_valid());
1005 label_group_node->append(phong_1_tag, dice_transaction);
1006 }
1007
1008 mi::math::Color_struct fg_col; fg_col.r = 0.25f; fg_col.g = 0.95f; fg_col.b = 0.25f; fg_col.a = 1.0f;
1009 mi::math::Color_struct bg_col; bg_col.r = 0.4f; bg_col.g = 0.5f; bg_col.b = 0.4f; bg_col.a = 0.5f;
1010
1011 m_label_tag_vec.clear();
1012 mi::math::Vector<mi::Float32, 3> label_pos (300.0f, 600.0f, 600.0f);
1013 std::string str = "View 0";
1014 const mi::Float32 height = 70.0f;
1015 const mi::Float32 width = -1.0f; // automated width
1016 mi::neuraylib::Tag created_label =
1017 create_append_label_to_group(scene_edit.get(), label_group_node.get(), label_pos, str,
1018 height, width, fg_col, bg_col, dice_transaction);
1019 check_success(created_label);
1020 m_label_tag_vec.push_back(created_label);
1021
1022 label_pos.y += 100.0f;
1023 str = "View 1";
1024 created_label =
1025 create_append_label_to_group(scene_edit.get(), label_group_node.get(), label_pos, str,
1026 height, width, fg_col, bg_col, dice_transaction);
1027 check_success(created_label.is_valid());
1028 m_label_tag_vec.push_back(created_label);
1029
1030 label_pos.y += 100.0f;
1031 str = "View 2";
1032 created_label =
1033 create_append_label_to_group(scene_edit.get(), label_group_node.get(), label_pos, str,
1034 height, width, fg_col, bg_col, dice_transaction);
1035 check_success(created_label.is_valid());
1036 m_label_tag_vec.push_back(created_label);
1037
1038 label_pos.y += 100.0f;
1039 str = "View 3";
1040 created_label =
1041 create_append_label_to_group(scene_edit.get(), label_group_node.get(), label_pos, str,
1042 height, width, fg_col, bg_col, dice_transaction);
1043 check_success(created_label.is_valid());
1044 m_label_tag_vec.push_back(created_label);
1045
1046 // Finally append everything to the root of the hierachical scene description
1047 const mi::neuraylib::Tag label_group_node_tag =
1048 dice_transaction->store_for_reference_counting(label_group_node.get());
1049 check_success(label_group_node_tag.is_valid());
1050 INFO_LOG << "Created a label_group: " << label_group_node_tag;
1051
1052 check_success(label_group_node_tag.is_valid());
1053 scene_edit->append(label_group_node_tag, dice_transaction);
1054 m_label_group_node_tag = label_group_node_tag;
1055 }
1056
1057 // Define a region of interest for the entire scene in the
1058 // scene's global coordinate system.
1059 // Set the region of interest
1060 check_success(m_roi.is_volume());
1061 scene_edit->set_clipped_bounding_box(m_roi);
1062
1063 // Set the scene global transformation matrix.
1064 mi::math::Matrix<mi::Float32, 4, 4> transform_mat(
1065 1.0f, 0.0f, 0.0f, 0.0f,
1066 0.0f, 1.0f, 0.0f, 0.0f,
1067 0.0f, 0.0f, 1.0f, 0.0f,
1068 0.0f, 0.0f, 0.0f, 1.0f
1069 );
1070
1071 scene_edit->set_transform_matrix(transform_mat);
1072
1073 // Create a camera
1074 mi::base::Handle< nv::index::IPerspective_camera > cam(
1075 scene_edit->create_camera<nv::index::IPerspective_camera>());
1076 check_success(cam.is_valid_interface());
1077 m_camera_tag = dice_transaction->store(cam.get());
1078 check_success(m_camera_tag.is_valid());
1079
1080 // set up the camera
1081 setup_camera(m_camera_tag, dice_transaction);
1082
1083 // ... and add the camera to the scene.
1084 scene_edit->set_camera(m_camera_tag);
1085}
1086
1087//----------------------------------------------------------------------
1088bool Multi_view_trimesh::setup_main_host()
1089{
1090 // Access the IndeX rendering query interface for querying performance values and pick results
1091 m_cluster_configuration =
1092 get_index_interface()->get_api_component<nv::index::ICluster_configuration>();
1093 check_success(m_cluster_configuration.is_valid_interface());
1094
1095 // create image canvas in application_layer
1096 m_image_file_canvas = create_image_file_canvas(get_application_layer_interface());
1097 check_success(m_image_file_canvas.is_valid_interface());
1098
1099 // Verifying that local host has joined
1100 // This may fail when there is a license problem.
1101 check_success(is_local_host_joined(m_cluster_configuration.get()));
1102
1103 // DiCE database access
1104 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
1105 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
1106 check_success(dice_transaction.is_valid_interface());
1107 {
1108 //----------------------------------------------------------------------
1109 // Setup session information
1110 m_session_tag =
1111 m_index_session->create_session(dice_transaction.get());
1112 check_success(m_session_tag.is_valid());
1113 mi::base::Handle<const nv::index::ISession> session(
1114 dice_transaction->access<nv::index::ISession>(
1115 m_session_tag));
1116 check_success(session.is_valid_interface());
1117
1118 // Setup the main multiple views, but it is empty at here.
1119 m_viewport_list = session->create_viewport_list();
1120 check_success(m_viewport_list.is_valid_interface());
1121
1122 //----------------------------------------------------------------------
1123 // Scene setup in the global scope
1124 setup_scene(dice_transaction.get());
1125 }
1126 dice_transaction->commit();
1127
1128 // Set canvas size
1129 const mi::math::Vector<mi::Uint32, 2> buffer_resolution(512, 512);
1130 m_image_file_canvas->set_resolution(buffer_resolution);
1131
1132 INFO_LOG << "Initialization complete.";
1133
1134 return true;
1135}
1136
1137//----------------------------------------------------------------------
1138// This example shows how to use multi-view functionality with a triangle mesh
1139int main(int argc, const char* argv[])
1140{
1141 nv::index::app::String_dict sdict;
1142 sdict.insert("dice::verbose", "4"); // log level
1143 sdict.insert("font_fpath", "/usr/share/fonts/dejavu/DejaVuSans.ttf"); // font path
1144 sdict.insert("mesh_file", "../create_trianglemesh/jacket.bin"); // input triangle mesh file name
1145 sdict.insert("mesh_bbox", "368.38 727.758 482.661 630.081 995.543 590.383"); // mesh bbox
1146 sdict.insert("mesh_mat_opacity_0", "1.0"); // mesh material opacity 0 (default 1.0, opaque)
1147 sdict.insert("mesh_mat_opacity_1", "0.5"); // mesh material opacity 1 (default 0.5)
1148 sdict.insert("roi", "0 0 0 650 1000 600"); // input roi
1149 sdict.insert("outfname", "frame_multi_view_trimesh"); // output file base name
1150 sdict.insert("verify_image_path_base", ""); // for unit test
1151 sdict.insert("unittest", "0"); // unit test mode
1152 sdict.insert("enable_vidx_vec", "1 1 1 1"); // enabled view indices vector
1153
1154 // Load IndeX library via Index_connect
1155 sdict.insert("dice::network::mode", "OFF");
1156
1157 // index setting
1158 sdict.insert("index::config::set_monitor_performance_values", "true");
1159 sdict.insert("index::service", "rendering_and_compositing");
1160 sdict.insert("index::cuda_debug_checks", "false");
1161
1162 // application_layer component loading
1163 sdict.insert("index::app::components::application_layer::component_name_list",
1164 "canvas_infrastructure image io");
1165 sdict.insert("index::app::plugins::base_importer::enabled", "true");
1166
1167 // Initialize application
1168 Multi_view_trimesh multi_view_trimesh;
1169 multi_view_trimesh.initialize(argc, argv, sdict);
1170 check_success(multi_view_trimesh.is_initialized());
1171
1172 // launch the application. creating the scene and rendering.
1173 const mi::Sint32 exit_code = multi_view_trimesh.launch();
1174 INFO_LOG << "Shutting down ...";
1175
1176 return exit_code;
1177}
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)