NVIDIA Index example code nvidia_logo_transpbg.gif Up
multi_view_heightfield.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/idistributed_data_access.h>
15#include <nv/index/idistributed_compute_technique.h>
16#include <nv/index/iheightfield_pick_result.h>
17#include <nv/index/iindex.h>
18#include <nv/index/iindex_debug_configuration.h>
19#include <nv/index/ilight.h>
20#include <nv/index/iline_set.h>
21#include <nv/index/imaterial.h>
22#include <nv/index/iscene.h>
23#include <nv/index/isession.h>
24#include <nv/index/itexture_filter_mode.h>
25#include <nv/index/iviewport.h>
26
27// Application layer component
28#include <nv/index/app/idata_analysis_and_processing.h>
29#include <nv/index/app/index_connect.h>
30#include <nv/index/app/string_dict.h>
31
32#include "utility/app_rendering_context.h"
33#include "utility/canvas_utility.h"
34
35#include <sstream>
36#include <iostream>
37
38//----------------------------------------------------------------------
40 public nv::index::app::Index_connect
41{
42public:
44 :
45 Index_connect()
46 {
47 // INFO_LOG << "DEBUG: Multi_view_heightfield() ctor";
48 }
49
51 {
52 // Note: Index_connect::~Index_connect() will be called after here.
53 // INFO_LOG << "DEBUG: ~Multi_view_heightfield() dtor";
54 }
55
56 // launch application
57 mi::Sint32 launch();
58
59protected:
60 virtual bool evaluate_options(nv::index::app::String_dict& sdict) CPP11_OVERRIDE;
61 // override
63 mi::neuraylib::INetwork_configuration* network_configuration,
64 nv::index::app::String_dict& options) CPP11_OVERRIDE
65 {
66 check_success(network_configuration != 0);
67
68 check_success(options.is_defined("unittest"));
69 const bool is_unittest = nv::index::app::get_bool(options.get("unittest"));
70 if (is_unittest)
71 {
72 info_cout("NETWORK: disabled networking mode.", options);
73 network_configuration->set_mode(mi::neuraylib::INetwork_configuration::MODE_OFF);
74 return true;
75 }
76
77 return initialize_networking_as_default_udp(network_configuration, options);
78 }
79
80private:
81 // visualize heightfield normal with lines
82 bool create_normal_line_set(
83 const mi::Float32* height_data,
84 const mi::math::Vector_struct<mi::Float32, 3>* normal_data,
85 const mi::math::Bbox<mi::Sint64, 2>& hf_bbox,
86 const mi::neuraylib::Tag& session_tag,
87 mi::neuraylib::IDice_transaction* dice_transaction);
88 // visualize heightfield normal with lines
89 void visualize_heightfield_normal(
90 mi::neuraylib::Tag heightfield_tag,
91 mi::neuraylib::Tag session_tag,
92 mi::neuraylib::IDice_transaction* dice_transaction);
93 // Setup camera to see this example scene
94 //
95 // \param[in] camera_tag camera tag
96 // \param[in] view_idx view index
97 // \param[in] dice_transaction dice transaction
98 void setup_camera(
99 const mi::neuraylib::Tag& camera_tag,
100 mi::Size view_idx,
101 mi::neuraylib::IDice_transaction* dice_transaction) const;
102 // localize scene elements
103 void localize_scene_element() const;
104
105 //----------------------------------------------------------------------
106 // Filter enable viewport index list
107 // \return newly created filtered viewport list
108 nv::index::IViewport_list* filter_enabled_viewport_index_list() const;
109 // Render one frame
110 // \param[in] frame_idx current frame index
111 // \return true when success
112 bool render_one_frame(mi::Sint32 frame_idx);
113 // create multiple viewports
114 //
115 // The viewport structure of this example
116 // (511,511) (pixel coordinates)
117 // +-----------------+-----------------+
118 // | 0. global scope | 1. view 1 |
119 // (0,256)| | camera change |(511,256)
120 // +-----------------+-----------------+
121 // (0,255)| 2. view 2 | 3. view 3 |(511,255)
122 // | add normal vis. | Mandelbrot tex. |
123 // +-----------------+-----------------+
124 // (0,0) (255,0) (256,0) (511,0)
125 //
126 //
127 // \param[in,out] arc application rendering context. multiple views will be updated.
128 void create_views() const;
129 //----------------------------------------------------------------------
130 // set up the scene
131 // Create a scene that contains a synthetically generated heightfield.
132 // \param[in] dice_transaction db transaction
133 void setup_scene(mi::neuraylib::IDice_transaction* dice_transaction);
134
135 //----------------------------------------------------------------------
136 // set up as the main host
137 // \return true when success
138 bool setup_main_host();
139 // print pick results
140 //
141 // \param[in] scene_pick_results scene pick result for one view
142 void print_pick_results(
143 nv::index::IScene_pick_results* scene_pick_results) const;
144 // pick test call.
145 //
146 // \param[in] pick_location_on_canvas picking location
147 // \param[in] iindex_query index query object
148 // \param[in] enable_view_vec enabled/disabled viewport state list
149 // \param[in] expected_is_hit hit is expected?
150 // \return true when expectation is satisfied
151 bool pick_test_call(
152 const mi::math::Vector<mi::Sint32, 2>& pick_location_on_canvas,
153 nv::index::IIndex_scene_query* iindex_query,
154 bool expected_is_hit) const;
155
156 // This session tag
157 mi::neuraylib::Tag m_session_tag;
158 // NVIDIA IndeX cluster configuration
159 mi::base::Handle<nv::index::ICluster_configuration> m_cluster_configuration;
160 // Application layer image file canvas (a render target)
161 mi::base::Handle<nv::index::app::canvas_infrastructure::IIndex_image_file_canvas> m_image_file_canvas;
162 // Create_icons options
163 std::string m_outfname;
164 bool m_is_unittest;
165 std::string m_verify_image_path_base;
166 std::vector<bool> m_enable_view_idx_vec;
167 // camera tag
168 mi::neuraylib::Tag m_camera_tag;
169 // heightfield scene element tag
170 mi::neuraylib::Tag m_heightfield_tag;
171 // normal line tag
172 mi::neuraylib::Tag m_normal_line_tag;
173 // phong tag
174 mi::neuraylib::Tag m_phong_1_tag;
175 // mandelbrot mapping tag
176 mi::neuraylib::Tag m_mandelbrot_map_tag;
177 // height value mapping tag
178 mi::neuraylib::Tag m_height_value_map_tag;
179 // static group node tag for heightfield
180 mi::neuraylib::Tag m_hf_static_group_node_tag;
181 mi::base::Handle<nv::index::IViewport_list> m_viewport_list;
182};
183
184//----------------------------------------------------------------------
186{
187 // setup
188 {
189 bool is_all_viewport_enabeld = true;
190 for (std::vector<bool>::const_iterator bi = m_enable_view_idx_vec.begin(); bi != m_enable_view_idx_vec.end(); ++bi)
191 {
192 is_all_viewport_enabeld = is_all_viewport_enabeld && (*bi);
193 }
194
195 check_success(setup_main_host());
196
197 // Create multiple views in the arc.
198 create_views();
199
200 mi::Sint32 frame_idx = 0;
201 // Need to render a frame before the data access.
202 {
203 const bool is_success = render_one_frame(frame_idx);
204 check_success(is_success);
205 ++frame_idx;
206 }
207
208 // visualize normal as line set at the global scope
209 {
210 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
211 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
212 check_success(dice_transaction.is_valid_interface());
213 {
214 visualize_heightfield_normal(m_heightfield_tag,
215 m_session_tag, dice_transaction.get());
216 }
217 dice_transaction->commit();
218 }
219
220 // localize scene elements
221 localize_scene_element();
222
223 // Render multiple views by a single render call
224 {
225 // Render a frame and save the rendered image to a file.
226 const bool is_success = render_one_frame(frame_idx);
227 check_success(is_success);
228 ++frame_idx;
229 }
230
231 // Pick test
232 {
233 const mi::Sint32 nb_pick_point = 3;
234 const mi::math::Vector<mi::Sint32, 2> pick_location_on_canvas[nb_pick_point] = {
235 // viewport 0, heightfield hit
236 mi::math::Vector<mi::Sint32, 2>(120, 400),
237 // viewport 0, none
238 mi::math::Vector<mi::Sint32, 2>( 45, 470),
239 // viewport 1, compute plane hit
240 mi::math::Vector<mi::Sint32, 2>(360, 390),
241 };
242 const bool is_hit[nb_pick_point] = {
243 true,
244 false,
245 true,
246 };
247
248 mi::base::Handle<nv::index::IIndex_scene_query> iindex_query(
249 get_index_interface()->get_api_component<nv::index::IIndex_scene_query>());
250 check_success(iindex_query.is_valid_interface());
251 for (mi::Sint32 i = 0; i < nb_pick_point; ++i)
252 {
253 const bool is_success =
254 pick_test_call(pick_location_on_canvas[i],
255 iindex_query.get(),
256 is_hit[i]);
257
258 if (!is_all_viewport_enabeld)
259 {
260 WARN_LOG << "Not all viewport is enabled, the pick test may fail.";
261 }
262 check_success(is_success);
263 }
264 }
265 }
266
267 return 0; // success (exit, otherwise)
268}
269
270//----------------------------------------------------------------------
271bool Multi_view_heightfield::evaluate_options(nv::index::app::String_dict& sdict)
272{
273 const std::string com_name = sdict.get("command:", "<unknown_command>");
274 m_is_unittest = nv::index::app::get_bool(sdict.get("unittest", "false"));
275
276 if (m_is_unittest)
277 {
278 sdict.insert("dice::verbose", "2");
279 }
280
281 m_outfname = sdict.get("outfname");
282 m_verify_image_path_base = sdict.get("verify_image_path_base");
283 m_enable_view_idx_vec = get_bool_vec_from_string(sdict.get("enable_vidx_vec"));
284
285 info_cout("running " + com_name, sdict);
286 info_cout("outfname = [" + m_outfname +
287 "], verify_image_path_base = [" + m_verify_image_path_base +
288 "], dice::verbose = " + sdict.get("dice::verbose"), sdict);
289
290 // print help and exit if -h
291 if (sdict.is_defined("h"))
292 {
293 std::cout
294 << "info: Usage: " << com_name << " [option]\n"
295 << "Option: [-h]\n"
296 << " print out this message\n"
297 << " [-dice::verbose severity_level]\n"
298 << " verbose severity level (3 is info). (default: " + sdict.get("dice::verbose")
299 << ")\n"
300
301 << " [-outfname string]\n"
302 << " output ppm file base name. When empty, no output.\n"
303 << " A frame number and extension (.ppm) will be added.\n"
304 << " (default: [" << m_outfname << "])\n"
305
306 << " [-verify_image_path_base image path basename]\n"
307 << " when image_fname path basename exist, verify the rendering images.\n"
308 << " (default: [" << m_verify_image_path_base << "])\n"
309
310 << " [-unittest bool]\n"
311 << " when true, unit test mode. "
312 << "(default: [" << m_is_unittest << "])\n"
313
314 << " [-enable_vidx_vec enabled_vector]\n"
315 << " Specify which viewport is enabled by a bool vector.\n"
316 << " (default: [" << sdict.get("enable_vidx_vec") << "])"
317
318 << std::endl;
319 exit(1);
320 }
321
322 return true;
323}
324
325//----------------------------------------------------------------------
326bool Multi_view_heightfield::create_normal_line_set(
327 const mi::Float32* height_data,
328 const mi::math::Vector_struct<mi::Float32, 3>* normal_data,
329 const mi::math::Bbox<mi::Sint64, 2>& hf_bbox,
330 const mi::neuraylib::Tag& session_tag,
331 mi::neuraylib::IDice_transaction* dice_transaction)
332{
333 check_success(dice_transaction != 0);
334 check_success(session_tag.is_valid());
335 check_success(height_data != 0);
336 check_success(normal_data != 0);
337 check_success(hf_bbox.volume() > 0);
338
339 mi::base::Handle< nv::index::ISession const > session(
340 dice_transaction->access<nv::index::ISession const>(session_tag));
341 check_success(session.is_valid_interface());
342
343 mi::base::Handle< nv::index::IScene > scene_edit(
344 dice_transaction->edit<nv::index::IScene>(session->get_scene()));
345 check_success(scene_edit.is_valid_interface());
346
347 // hierarchical scene description node for the point set
348 mi::base::Handle<nv::index::ITransformed_scene_group> group_node(
349 scene_edit->create_scene_group<nv::index::ITransformed_scene_group>());
350 check_success(group_node.is_valid_interface());
351
352 // Line coordinates and its attributes. According to the
353 // attributes, color and width are defined.
354 // Here, we create two line sets.
355 std::vector<mi::math::Vector_struct<mi::Float32, 3> > line_seg_vec;
356 std::vector<mi::math::Color_struct> color_vec;
357 mi::math::Color_struct red_color = { 1.0f, 0.0f, 0.0f, 1.0f, };
358 std::vector<mi::Float32> width_vec;
359 mi::Float32 vis_line_len = 60.0f;
360 mi::Sint64 x_step = 16;
361 mi::Sint64 y_step = 8;
362
363 // data access
364 mi::math::Vector<mi::Sint64, 2> ij(0, 0);
365 for (ij[0] = hf_bbox.min[0]; ij[0] < hf_bbox.max[0]; ij[0] += x_step)
366 {
367 for (ij[1] = hf_bbox.min[1]; ij[1] < hf_bbox.max[1]; ij[1] += y_step)
368 {
369 {
370 mi::Sint64 idx = get_heightfield_index(ij, hf_bbox);
371 mi::math::Vector<mi::Float32, 3> org_pos(
372 static_cast<mi::Float32>(ij[0]),
373 static_cast<mi::Float32>(ij[1]),
374 static_cast<mi::Float32>(height_data[idx]));
375
376 mi::math::Vector<mi::Float32, 3> dst_pos = org_pos +
377 vis_line_len * mi::math::Vector<mi::Float32, 3>(normal_data[idx]);
378
379 line_seg_vec.push_back(org_pos);
380 line_seg_vec.push_back(dst_pos);
381 color_vec.push_back(red_color);
382 width_vec.push_back(1.0f);
383 }
384 {
385 mi::math::Vector<mi::Sint64, 2> ij_x_next = ij;
386 ++(ij_x_next[0]);
387 if (ij_x_next[0] < hf_bbox.max[0])
388 {
389 mi::Sint64 idx = get_heightfield_index(ij_x_next, hf_bbox);
390
391 mi::math::Vector<mi::Float32, 3> org_pos(
392 static_cast<mi::Float32>(ij_x_next[0]),
393 static_cast<mi::Float32>(ij_x_next[1]),
394 static_cast<mi::Float32>(height_data[idx]));
395
396 mi::math::Vector<mi::Float32, 3> dst_pos = org_pos +
397 vis_line_len * mi::math::Vector<mi::Float32, 3>(normal_data[idx]);
398
399 line_seg_vec.push_back(org_pos);
400 line_seg_vec.push_back(dst_pos);
401 color_vec.push_back(red_color);
402 width_vec.push_back(1.0f);
403 }
404 }
405 }
406 }
407
408 {
409 // Create line_set scene element and add it to the scene
410 mi::base::Handle<nv::index::ILine_set> line_set(scene_edit->create_shape<nv::index::ILine_set>());
411 check_success(line_set.is_valid_interface());
412 line_set->set_line_type(nv::index::ILine_set::LINE_TYPE_SEGMENTS);
413
414 line_set->set_lines(&(line_seg_vec[0]), line_seg_vec.size()); // may cut the last point
415 line_set->set_colors(&(color_vec[0]), color_vec.size());
416 line_set->set_widths(&(width_vec[0]), width_vec.size());
417
418 // Add the line segments to the database
419 const mi::neuraylib::Tag line_set_tag = dice_transaction->store_for_reference_counting(line_set.get());
420 check_success(line_set_tag.is_valid());
421 check_success(!(m_normal_line_tag.is_valid()));
422 m_normal_line_tag = line_set_tag;
423
424 // Add to the scene description
425 group_node->append(line_set_tag, dice_transaction);
426 INFO_LOG << "Added line_set (size: " << line_seg_vec.size() << ") to the scene (tag id: "
427 << line_set_tag.id << ").";
428 }
429
430 mi::neuraylib::Tag group_node_tag = dice_transaction->store_for_reference_counting(group_node.get());
431 check_success(group_node_tag.is_valid());
432 scene_edit->append(group_node_tag, dice_transaction);
433
434 return true;
435}
436
437//----------------------------------------------------------------------
438void Multi_view_heightfield::visualize_heightfield_normal(
439 mi::neuraylib::Tag heightfield_tag,
440 mi::neuraylib::Tag session_tag,
441 mi::neuraylib::IDice_transaction* dice_transaction)
442{
443 check_success(heightfield_tag.is_valid());
444 check_success(session_tag.is_valid());
445 check_success(dice_transaction != 0);
446
447 mi::base::Handle<const nv::index::ISession> session(
448 dice_transaction->access<nv::index::ISession>(session_tag));
449 check_success(session.is_valid_interface());
450
451 mi::base::Handle<const nv::index::IRegular_heightfield> heightfield(
452 dice_transaction->access<nv::index::IRegular_heightfield>(heightfield_tag));
453 check_success(heightfield.is_valid_interface());
454
455 const mi::math::Bbox<mi::Float32, 3> heightfield_bbox = heightfield->get_IJK_bounding_box();
456
457 const mi::math::Bbox<mi::Uint32, 2> query_bbox(
458 static_cast<mi::Uint32>(heightfield_bbox.min.x), static_cast<mi::Uint32>(heightfield_bbox.min.y),
459 static_cast<mi::Uint32>(heightfield_bbox.max.x), static_cast<mi::Uint32>(heightfield_bbox.max.y));
460
461 // Access the distribution scheme
462 const mi::neuraylib::Tag dist_layout_tag = session->get_distribution_layout();
463 check_success(dist_layout_tag.is_valid());
464
465 mi::base::Handle<const nv::index::IData_distribution> distribution_layout(
466 dice_transaction->access<nv::index::IData_distribution>(dist_layout_tag));
467 check_success(distribution_layout.is_valid_interface());
468
469 // Find out on which hosts the data is located and print this information
470 mi::base::Handle<nv::index::Regular_heightfield_locality_query_mode> mode(
471 new nv::index::Regular_heightfield_locality_query_mode(heightfield_tag, query_bbox, false));
472 mi::base::Handle<nv::index::IDistributed_data_locality> data_locality(
473 distribution_layout->get_data_locality<nv::index::IRegular_heightfield>(mode.get(), dice_transaction));
474 check_success(data_locality.is_valid_interface());
475
476 std::ostringstream hosts;
477 for (mi::Uint32 i = 0; i < data_locality->get_nb_cluster_nodes(); ++i)
478 {
479 check_success(data_locality->get_cluster_node(i) != 0);
480 hosts << data_locality->get_cluster_node(i) << " ";
481 }
482 INFO_LOG << "Height field data for the current query bbox is located on these hosts: " << hosts.str();
483
484 // Create the access factory
485 const mi::neuraylib::Tag data_access_tag = session->get_data_access_factory();
486 check_success(data_access_tag.is_valid());
487
488 mi::base::Handle<const nv::index::IDistributed_data_access_factory> access_factory(
489 dice_transaction->access<nv::index::IDistributed_data_access_factory>(data_access_tag));
490 check_success(access_factory.is_valid_interface());
491
492 mi::base::Handle<nv::index::IRegular_heightfield_data_access> heightfield_data_access(
493 access_factory->create_regular_heightfield_data_access(heightfield_tag));
494 check_success(heightfield_data_access.is_valid_interface());
495
496 // Now retrieve the data
497 heightfield_data_access->access(query_bbox, dice_transaction);
498
499 const mi::math::Bbox<mi::Uint32, 2> effective_bbox = heightfield_data_access->get_patch_bounding_box();
500 check_success(effective_bbox == query_bbox);
501
502 // Average the contents of the trace
503 const mi::Float32* height_data = heightfield_data_access->get_elevation_values();
504 const mi::math::Vector_struct<mi::Float32, 3>* normal_data = heightfield_data_access->get_normal_values();
505 const mi::math::Bbox<mi::Sint64, 2> hf_bbox(effective_bbox);
506
507 create_normal_line_set(height_data,
508 normal_data,
509 hf_bbox,
510 session_tag,
511 dice_transaction);
512}
513
514//----------------------------------------------------------------------
515void Multi_view_heightfield::setup_camera(
516 const mi::neuraylib::Tag& camera_tag,
517 mi::Size view_idx,
518 mi::neuraylib::IDice_transaction* dice_transaction) const
519{
520 check_success(camera_tag.is_valid());
521
522 mi::base::Handle<nv::index::IPerspective_camera> cam(
523 dice_transaction->edit<nv::index::IPerspective_camera>(camera_tag));
524 check_success(cam.is_valid_interface());
525
526 // Set the camera parameters to see the whole scene
527 const mi::math::Vector<mi::Float32, 3> from(700.0f, 700.0f, 200.0f);
528 mi::math::Vector<mi::Float32, 3> dir ( -1.125f, -1.125f, -1.0f);
529 const mi::math::Vector<mi::Float32, 3> up ( 0.0f, 0.0f, 1.0f);
530 dir.normalize();
531
532 cam->set(from, dir, up);
533 cam->set_aperture(0.033f);
534 cam->set_aspect(1.0f);
535 cam->set_focal(0.03f);
536 cam->set_clip_min(2.0f);
537 cam->set_clip_max(1000.0f);
538}
539
540//----------------------------------------------------------------------
541void Multi_view_heightfield::localize_scene_element() const
542{
543 check_success(m_viewport_list.is_valid_interface());
544
545 // Process local views first.
546
547 // Set up view 1: change the camera
548 {
549 const mi::Size view_idx = 1;
550 check_success(m_viewport_list->size() > view_idx);
551
552 mi::base::Handle<nv::index::IViewport> viewport(m_viewport_list->get(view_idx));
553 check_success(viewport != 0);
554
555 mi::base::Handle<mi::neuraylib::IScope> cur_scope(viewport->get_scope());
556 check_success(cur_scope);
557 check_success(std::string(cur_scope->get_id()) == "1");
558
559 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
560 cur_scope->create_transaction<mi::neuraylib::IDice_transaction>());
561 check_success(dice_transaction.is_valid_interface());
562
563 // localize scene elements
564 {
565 mi::Sint32 ret_localize = 1;
566 ret_localize = dice_transaction->localize(m_camera_tag,
567 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
568 check_success(ret_localize == 0);
569
570 mi::base::Handle<nv::index::ICamera> cam(
571 dice_transaction->edit<nv::index::ICamera>(m_camera_tag));
572 check_success(cam.is_valid_interface());
573
574 const mi::math::Vector<mi::Float32, 3> from(0.0f, 700.0f, 200.0f);
575 mi::math::Vector<mi::Float32, 3> dir (1.0f, -1.125f, -1.0f);
576 const mi::math::Vector<mi::Float32, 3> up ( 0.0f, 0.0f, 1.0f);
577 dir.normalize();
578
579 cam->set(from, dir, up);
580 }
581 dice_transaction->commit();
582 }
583
584 // Set up view 2: height color + normal lines
585 {
586 const mi::Size view_idx = 2;
587 check_success(m_viewport_list->size() > view_idx);
588
589 mi::base::Handle<nv::index::IViewport> viewport(m_viewport_list->get(view_idx));
590 check_success(viewport != 0);
591
592
593 mi::base::Handle<mi::neuraylib::IScope> cur_scope(viewport->get_scope());
594 check_success(cur_scope);
595 check_success(std::string(cur_scope->get_id()) == "2");
596
597 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
598 cur_scope->create_transaction<mi::neuraylib::IDice_transaction>());
599 check_success(dice_transaction.is_valid_interface());
600
601 // localize scene elements
602 {
603 mi::Sint32 ret_localize = 1;
604 ret_localize = dice_transaction->localize(m_normal_line_tag,
605 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
606 check_success(ret_localize == 0);
607 ret_localize = dice_transaction->localize(m_mandelbrot_map_tag,
608 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
609 check_success(ret_localize == 0);
610 ret_localize = dice_transaction->localize(m_height_value_map_tag,
611 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
612 check_success(ret_localize == 0);
613
614 mi::base::Handle<nv::index::ILine_set> line_set(
615 dice_transaction->edit<nv::index::ILine_set>(m_normal_line_tag));
616 check_success(line_set.is_valid_interface());
617 line_set->set_enabled(true);
618
619 mi::base::Handle<nv::index::IDistributed_compute_technique> man_map(
620 dice_transaction->edit<nv::index::IDistributed_compute_technique>(m_mandelbrot_map_tag));
621 man_map->set_enabled(false);
622
623 mi::base::Handle<nv::index::IDistributed_compute_technique> hv_map(
624 dice_transaction->edit<nv::index::IDistributed_compute_technique>(m_height_value_map_tag));
625 hv_map->set_enabled(true);
626
627 mi::base::Handle<nv::index::IPhong_gl> phong_1(
628 dice_transaction->edit<nv::index::IPhong_gl>(m_phong_1_tag));
629 check_success(phong_1.is_valid_interface());
630
631 // Use just ambient white with texture
632 phong_1->set_ambient(mi::math::Color(1.0f));
633 phong_1->set_diffuse(mi::math::Color(0.0f));
634 phong_1->set_specular(mi::math::Color(0.0f));
635 }
636 dice_transaction->commit();
637 }
638
639 // Set up view 3: Mandelbrot texture
640 {
641 const mi::Size view_idx = 3;
642 check_success(m_viewport_list->size() > view_idx);
643
644 mi::base::Handle<nv::index::IViewport> viewport(m_viewport_list->get(view_idx));
645 check_success(viewport != 0);
646
647 mi::base::Handle<mi::neuraylib::IScope> cur_scope(viewport->get_scope());
648 check_success(cur_scope);
649 check_success(std::string(cur_scope->get_id()) == "3");
650
651 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
652 cur_scope->create_transaction<mi::neuraylib::IDice_transaction>());
653 check_success(dice_transaction.is_valid_interface());
654
655 // localize scene elements
656 {
657 mi::Sint32 ret_localize = 1;
658 ret_localize = dice_transaction->localize(m_phong_1_tag,
659 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
660 check_success(ret_localize == 0);
661 ret_localize = dice_transaction->localize(m_mandelbrot_map_tag,
662 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
663 check_success(ret_localize == 0);
664 ret_localize = dice_transaction->localize(m_height_value_map_tag,
665 mi::neuraylib::IDice_transaction::LOCAL_SCOPE);
666 check_success(ret_localize == 0);
667
668 mi::base::Handle<nv::index::IDistributed_compute_technique> man_map(
669 dice_transaction->edit<nv::index::IDistributed_compute_technique>(m_mandelbrot_map_tag));
670 man_map->set_enabled(true);
671
672 mi::base::Handle<nv::index::IDistributed_compute_technique> hv_map(
673 dice_transaction->edit<nv::index::IDistributed_compute_technique>(m_height_value_map_tag));
674 hv_map->set_enabled(false);
675
676 mi::base::Handle<nv::index::IPhong_gl> phong_1(
677 dice_transaction->edit<nv::index::IPhong_gl>(m_phong_1_tag));
678 check_success(phong_1.is_valid_interface());
679
680 // Use just ambient white with texture
681 phong_1->set_ambient(mi::math::Color(1.0f));
682 phong_1->set_diffuse(mi::math::Color(0.0f));
683 phong_1->set_specular(mi::math::Color(0.0f));
684 }
685 dice_transaction->commit();
686 }
687
688 // Set up view 0, global: disable normal lines
689 {
690 const mi::Size view_idx = 0;
691 check_success(m_viewport_list->size() > view_idx);
692
693 mi::base::Handle<nv::index::IViewport> viewport(m_viewport_list->get(view_idx));
694 check_success(viewport != 0);
695
696 mi::base::Handle<mi::neuraylib::IScope> cur_scope(viewport->get_scope());
697 check_success(cur_scope);
698 check_success(std::string(cur_scope->get_id()) == "0");
699
700 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
701 cur_scope->create_transaction<mi::neuraylib::IDice_transaction>());
702 check_success(dice_transaction.is_valid_interface());
703
704 // edit scene elements
705 {
706 mi::base::Handle<nv::index::ILine_set> line_set(
707 dice_transaction->edit<nv::index::ILine_set>(m_normal_line_tag));
708 check_success(line_set.is_valid_interface());
709 line_set->set_enabled(false);
710 }
711 dice_transaction->commit();
712 }
713}
714
715//----------------------------------------------------------------------
716nv::index::IViewport_list* Multi_view_heightfield::filter_enabled_viewport_index_list() const
717{
718 mi::base::Handle<nv::index::IViewport_list> new_viewport_list;
719 {
720 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
721 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
722 assert(dice_transaction.is_valid_interface());
723 {
724 assert(m_session_tag.is_valid());
725 mi::base::Handle<const nv::index::ISession> session(
726 dice_transaction->access<nv::index::ISession>(m_session_tag));
727 assert(session.is_valid_interface());
728
729 // create viewport from a session
730 new_viewport_list = session->create_viewport_list();
731 }
732 dice_transaction->commit();
733 }
734
735 check_success(new_viewport_list.is_valid_interface());
736 const mi::Size nb_views = m_viewport_list->size();
737
738 std::stringstream sstr;
739 mi::Size nb_enabled = 0;
740 for (mi::Size i = 0; i < nb_views; ++i)
741 {
742 if (m_enable_view_idx_vec[i])
743 {
744 sstr << i << " ";
745 mi::base::Handle<nv::index::IViewport> vp (m_viewport_list->get(i));
746 new_viewport_list->append(vp.get());
747 ++nb_enabled;
748 }
749 }
750 // copy advisory state
751 new_viewport_list->set_advisory_enabled(m_viewport_list->get_advisory_enabled());
752
753 if (nb_enabled == nb_views)
754 {
755 INFO_LOG << "All views are enabled.";
756 }
757 else
758 {
759 INFO_LOG << "Filtered views. Enabled: " << sstr.str();
760 }
761
762 new_viewport_list->retain();
763 return new_viewport_list.get();
764}
765
766//----------------------------------------------------------------------
767bool Multi_view_heightfield::render_one_frame(mi::Sint32 frame_idx)
768{
769 bool success = true;
770
771 // Render a frame and save the rendered image to a file.
772 // Only save the file at the end of the iteration.
773 std::string fname = "";
774 check_success(!(m_outfname.empty()));
775 {
776 fname = get_output_file_name(m_outfname, frame_idx);
777 }
778 check_success(m_index_rendering.is_valid_interface());
779
780 // set up canvas. output_fname.empty() is valid (no output file)
781 m_image_file_canvas->set_rgba_file_name(fname.c_str());
782
783 // set advisory to see the multiview rendering details
784 m_viewport_list->set_advisory_enabled(true);
785
786 mi::base::Handle<nv::index::IViewport_list> cur_viewport_list(
787 filter_enabled_viewport_index_list());
788 check_success(cur_viewport_list.is_valid_interface());
789
790 mi::base::Handle<nv::index::IFrame_results_list> frame_results_list(
791 m_index_rendering->render(
792 m_session_tag,
793 m_image_file_canvas.get(),
794 cur_viewport_list.get()));
795 check_success(frame_results_list.is_valid_interface());
796
797 if (frame_results_list->size() == 0)
798 {
799 ERROR_LOG << "IIndex_rendering rendering call has no results.";
800 success = false;
801 }
802 else
803 {
804 for (mi::Size i = 0; i < frame_results_list->size(); ++i)
805 {
806 mi::base::Handle<nv::index::IFrame_results>
807 frame_results(frame_results_list->get(i));
808 check_success(frame_results.is_valid_interface());
809
810 const mi::base::Handle<nv::index::IError_set> err_set(frame_results->get_error_set());
811 check_success(err_set.is_valid_interface());
812 if (err_set->any_errors())
813 {
814 std::ostringstream os;
815
816 const mi::base::Handle<nv::index::IError_set> err_set(frame_results->get_error_set());
817 const mi::Uint32 nb_err = err_set->get_nb_errors();
818 for (mi::Uint32 e = 0; e < nb_err; ++e)
819 {
820 if (e != 0) os << '\n';
821 const mi::base::Handle<nv::index::IError> err(err_set->get_error(e));
822 os << err->get_error_string();
823 }
824
825 ERROR_LOG << "IIndex_rendering rendering call failed with the following error(s): " << '\n'
826 << os.str();
827 success = false;
828 }
829 }
830 }
831
832 // verify the generated frame
833 if (!(m_verify_image_path_base.empty()))
834 {
835 const std::string ref_img_fpath = get_output_file_name(m_verify_image_path_base, frame_idx);
836 if (!(verify_canvas_result(get_application_layer_interface(),
837 m_image_file_canvas.get(), ref_img_fpath, get_options())))
838 {
839 success = false;
840 }
841 }
842
843 return success;
844}
845
846//----------------------------------------------------------------------
847void Multi_view_heightfield::create_views() const
848{
849 // Check session and multiple views in the arc
850 check_success(m_session_tag.is_valid());
851 check_success(m_viewport_list.is_valid_interface());
852 check_success(m_viewport_list->size() == 0);
853
854 // Multiple view itself lives in the global scope.
855 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
856 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
857 check_success(dice_transaction.is_valid_interface());
858 {
859 mi::base::Handle<const nv::index::ISession> session(
860 dice_transaction->access<nv::index::ISession>(m_session_tag));
861 check_success(session.is_valid_interface());
862
863 // 0. create a single view in the global scope.
864 {
865 mi::base::Handle<nv::index::IViewport> viewport(session->create_viewport());
866 check_success(viewport.is_valid_interface());
867
868 const mi::math::Vector<mi::Sint32, 2> viewport_pos( 0, 256);
869 const mi::math::Vector<mi::Sint32, 2> viewport_size(256, 256);
870
871 viewport->set_position(viewport_pos);
872 viewport->set_size(viewport_size);
873 viewport->set_scope(m_global_scope.get()); // ref count up
874
875 m_viewport_list->append(viewport.get());
876
877 // set up the camera
878 const mi::Size view_idx = 0;
879 setup_camera(m_camera_tag, view_idx, dice_transaction.get());
880 }
881
882 // 1. viewport
883 {
884 mi::base::Handle<nv::index::IViewport> viewport(session->create_viewport());
885 check_success(viewport.is_valid_interface());
886
887 mi::neuraylib::IScope* parent = 0; // this means global scope in this context
888 mi::Uint8 privacy_level = 1;
889 bool is_temp = false;
890 mi::base::Handle<mi::neuraylib::IScope> local_scope(m_database->create_scope(parent, privacy_level, is_temp));
891 check_success(local_scope.is_valid_interface());
892
893 const mi::math::Vector<mi::Sint32, 2> viewport_pos( 256, 256);
894 const mi::math::Vector<mi::Sint32, 2> viewport_size(256, 256);
895
896 viewport->set_position(viewport_pos);
897 viewport->set_size(viewport_size);
898 viewport->set_scope(local_scope.get()); // ref count up
899
900 m_viewport_list->append(viewport.get());
901 }
902
903 // 2. viewport
904 {
905 mi::base::Handle<nv::index::IViewport> viewport(session->create_viewport());
906 check_success(viewport.is_valid_interface());
907
908 mi::neuraylib::IScope* parent = 0; // this means global scope in this context
909 mi::Uint8 privacy_level = 1;
910 bool is_temp = false;
911 mi::base::Handle<mi::neuraylib::IScope> local_scope(m_database->create_scope(parent, privacy_level, is_temp));
912 check_success(local_scope.is_valid_interface());
913
914 const mi::math::Vector<mi::Sint32, 2> viewport_pos( 0, 0);
915 const mi::math::Vector<mi::Sint32, 2> viewport_size(256, 256);
916
917 viewport->set_position(viewport_pos);
918 viewport->set_size(viewport_size);
919 viewport->set_scope(local_scope.get()); // ref count up
920
921 m_viewport_list->append(viewport.get());
922 }
923
924 // 3. viewport
925 {
926 mi::base::Handle<nv::index::IViewport> viewport(session->create_viewport());
927 check_success(viewport.is_valid_interface());
928
929 mi::neuraylib::IScope* parent = 0; // this means global scope in this context
930 mi::Uint8 privacy_level = 1;
931 bool is_temp = false;
932 mi::base::Handle<mi::neuraylib::IScope> local_scope(m_database->create_scope(parent, privacy_level, is_temp));
933 check_success(local_scope.is_valid_interface());
934
935 const mi::math::Vector<mi::Sint32, 2> viewport_pos( 256, 0);
936 const mi::math::Vector<mi::Sint32, 2> viewport_size(256, 256);
937
938 viewport->set_position(viewport_pos);
939 viewport->set_size(viewport_size);
940 viewport->set_scope(local_scope.get()); // ref count up
941
942 m_viewport_list->append(viewport.get());
943 }
944 }
945 dice_transaction->commit();
946}
947
948
949//----------------------------------------------------------------------
950void Multi_view_heightfield::setup_scene(
951 mi::neuraylib::IDice_transaction* dice_transaction)
952{
953 check_success(dice_transaction != 0);
954
955 // Access the session instance from the database.
956 mi::base::Handle<const nv::index::ISession> session(
957 dice_transaction->access<const nv::index::ISession>(m_session_tag));
958 check_success(session.is_valid_interface());
959
960 // Access (edit mode) the scene instance from the database.
961 mi::base::Handle<nv::index::IScene> scene_edit(
962 dice_transaction->edit<nv::index::IScene>(session->get_scene()));
963 check_success(scene_edit.is_valid_interface());
964
965 // Create static group node for large data
966 mi::base::Handle<nv::index::IStatic_scene_group> static_group_node(
967 scene_edit->create_scene_group<nv::index::IStatic_scene_group>());
968 check_success(static_group_node.is_valid_interface());
969
970 // Details for creating a synthetic heightfield.
971 const mi::math::Vector<mi::Uint32, 2> heightfield_size(500, 500);
972
973 nv::index::app::String_dict heightfield_opt;
974 heightfield_opt.insert("args::type", "heightfield");
975 heightfield_opt.insert("args::importer", "nv::index::plugin::legacy_importer.Synthetic_heightfield_generator");
976 heightfield_opt.insert("args::synthetic_type", "i");
977 heightfield_opt.insert("args::size", "500 500");
978 heightfield_opt.insert("args::range", "0.1 1000");
979 nv::index::IDistributed_data_import_callback* importer_callback =
980 get_importer_from_application_layer(
981 get_application_layer_interface(),
982 "nv::index::plugin::legacy_importer.Synthetic_heightfield_generator",
983 heightfield_opt);
984
985
986 // Create heightfield scene element and add it to the scene
987 const mi::Float32 rotate_k = 0.0f;
988 const mi::math::Vector<mi::Float32, 3> translate(0.0f, 0.0f, 0.0f);
989 const mi::math::Vector<mi::Float32, 3> scale(1.0f, 1.0f, 1.0f);
990 // const mi::math::Vector<mi::Float32, 2> elevation_range(50.0f, 256.0f);
991 const mi::math::Vector<mi::Float32, 2> elevation_range(0.0f, 256.0f);
992
993 mi::base::Handle<nv::index::IRegular_heightfield> heightfield_scene_element(
994 scene_edit->create_regular_heightfield(
995 scale, rotate_k, translate,
996 heightfield_size,
997 elevation_range,
998 importer_callback,
999 dice_transaction));
1000 check_success(heightfield_scene_element.is_valid_interface());
1001
1002 const mi::math::Bbox<mi::Float32, 3> heightfield_bbox = heightfield_scene_element->get_IJK_bounding_box();
1003
1004 // Set the name of the heightfield scene element
1005 const std::string heightfield_name = "synthetic heightfield";
1006 heightfield_scene_element->set_name(heightfield_name.c_str());
1007
1008 // Store the heightfield scene element in the DB
1009 const mi::neuraylib::Tag heightfield_tag =
1010 dice_transaction->store_for_reference_counting(heightfield_scene_element.get());
1011 check_success(heightfield_tag.is_valid());
1012 check_success(!m_heightfield_tag.is_valid());
1013 m_heightfield_tag = heightfield_tag;
1014
1015 // Add a light and a material to the static group node
1016 {
1017 // Add a light
1018 mi::base::Handle<nv::index::IDirectional_headlight> headlight(
1019 scene_edit->create_attribute<nv::index::IDirectional_headlight>());
1020 check_success(headlight.is_valid_interface());
1021 const mi::math::Color color_intensity(1.0f, 1.0f, 1.0f, 1.0f);
1022 headlight->set_intensity(color_intensity);
1023 headlight->set_direction(mi::math::Vector<mi::Float32, 3>(1.0f, -1.0f, -1.0f));
1024 const mi::neuraylib::Tag headlight_tag = dice_transaction->store_for_reference_counting(headlight.get());
1025 check_success(headlight_tag.is_valid());
1026 static_group_node->append(headlight_tag, dice_transaction);
1027
1028 // Material for the heightfield
1029 mi::base::Handle<nv::index::IPhong_gl> phong_1(scene_edit->create_attribute<nv::index::IPhong_gl>());
1030 check_success(phong_1.is_valid_interface());
1031
1032 // Define a more interesting greenish material
1033 phong_1->set_ambient(mi::math::Color(0.f, 0.3f, 0.0f, 0.3f));
1034 phong_1->set_diffuse(mi::math::Color(0.f, 0.8f, 0.2f, 0.3f));
1035 phong_1->set_specular(mi::math::Color(0.6f));
1036 phong_1->set_shininess(100.f);
1037
1038 const mi::neuraylib::Tag phong_1_tag
1039 = dice_transaction->store_for_reference_counting(phong_1.get());
1040 check_success(phong_1_tag.is_valid());
1041 check_success(!(m_phong_1_tag.is_valid()));
1042 m_phong_1_tag = phong_1_tag;
1043
1044 static_group_node->append(phong_1_tag, dice_transaction);
1045 }
1046
1047 // Put a computed texture onto the heightfield. Both disabled in default
1048 // Mandelbrot texture
1049 {
1050 // Create the computed texture, with a size fitting the heightfield
1051 mi::base::Handle<nv::index::ITexture_filter_mode> tex_filter(
1052 scene_edit->create_attribute<nv::index::ITexture_filter_mode_nearest_neighbor>());
1053 check_success(tex_filter.is_valid_interface());
1054 mi::neuraylib::Tag tex_filter_tag = dice_transaction->store_for_reference_counting(tex_filter.get());
1055 check_success(tex_filter_tag.is_valid());
1056 static_group_node->append(tex_filter_tag, dice_transaction);
1057
1058 mi::base::Handle<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing> processing(
1059 get_application_layer_interface()->get_api_component<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing>());
1060 check_success(processing.is_valid_interface());
1061 // Create a mandelbrot technique and add it to the scene. For more details on how to implement the checkerboard, please review the provided
1062 // source that was shipped with the application layer component 'nv::index::app::data_analysis_and_processing::IData_analysis_and_processing'.
1063 mi::base::Handle<nv::index::IDistributed_compute_technique> man_map(
1064 processing->get_sample_tool_set()->create_mandelbrot_2d_technique(mi::math::Vector<mi::Float32, 2>(1250.f, 680.f)));
1065 check_success(man_map.is_valid_interface());
1066 man_map->set_enabled(false);
1067
1068 // Add the mapping to the scene before the heightfield
1069 mi::neuraylib::Tag man_map_tag = dice_transaction->store_for_reference_counting(man_map.get());
1070 check_success(man_map_tag.is_valid());
1071 check_success(!m_mandelbrot_map_tag.is_valid());
1072 m_mandelbrot_map_tag = man_map_tag;
1073
1074 static_group_node->append(man_map_tag, dice_transaction);
1075 }
1076
1077 // Map height values in the heightfield to colors
1078 {
1079 // Create the computed texture, passing the height range of the heightfield
1080 const mi::math::Vector<mi::Float32, 2> height_range(
1081 heightfield_bbox.min.z, heightfield_bbox.max.z);
1082
1083 mi::base::Handle<nv::index::ITexture_filter_mode> tex_filter(
1084 scene_edit->create_attribute<nv::index::ITexture_filter_mode_nearest_neighbor>());
1085 check_success(tex_filter.is_valid_interface());
1086 mi::neuraylib::Tag tex_filter_tag = dice_transaction->store_for_reference_counting(tex_filter.get());
1087 check_success(tex_filter_tag.is_valid());
1088 static_group_node->append(tex_filter_tag, dice_transaction);
1089
1090 // Create the computed texture, with a size fitting the heightfield
1091 mi::base::Handle<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing> processing(
1092 get_application_layer_interface()->get_api_component<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing>());
1093 check_success(processing.is_valid_interface());
1094 // Create a mandelbrot technique and add it to the scene. For more details on how to implement the checkerboard, please review the provided
1095 // source that was shipped with the application layer component 'nv::index::app::data_analysis_and_processing::IData_analysis_and_processing'.
1096 const mi::math::Color color0(0.f, 1.f, 0.f, 1.f); // green
1097 const mi::math::Color color1(1.f, 0.f, 0.f, 1.f); // red
1098 mi::base::Handle<nv::index::IDistributed_compute_technique> hv_map(
1099 processing->get_sample_tool_set()->create_color_encoded_elevation_technique(height_range, color0, color1));
1100 check_success(hv_map.is_valid_interface());
1101 hv_map->set_enabled(true);
1102
1103 // Add the mapping to the scene before the heightfield
1104 mi::neuraylib::Tag hv_map_tag = dice_transaction->store_for_reference_counting(hv_map.get());
1105 check_success(hv_map_tag.is_valid());
1106 check_success(!m_height_value_map_tag.is_valid());
1107 m_height_value_map_tag = hv_map_tag;
1108
1109 static_group_node->append(hv_map_tag, dice_transaction);
1110 }
1111
1112 // Append the heightfield to the scene group
1113 static_group_node->append(heightfield_tag, dice_transaction);
1114 mi::neuraylib::Tag static_group_node_tag =
1115 dice_transaction->store_for_reference_counting(static_group_node.get());
1116 check_success(static_group_node_tag.is_valid());
1117 check_success(!m_hf_static_group_node_tag.is_valid());
1118 m_hf_static_group_node_tag = static_group_node_tag;
1119
1120 // Append the static scene group to the scene.
1121 scene_edit->append(static_group_node_tag, dice_transaction);
1122
1123 std::stringstream sstr;
1124 sstr << "Created an synthetic heightfield: size = "
1125 << heightfield_size << ", tag = " << heightfield_tag.id;
1126 INFO_LOG << sstr.str();
1127
1128 // Create a camera and adjust the camera parameter.
1129 mi::base::Handle< nv::index::IPerspective_camera > cam(
1130 scene_edit->create_camera<nv::index::IPerspective_camera>());
1131 check_success(cam.is_valid_interface());
1132 m_camera_tag = dice_transaction->store(cam.get());
1133
1134 check_success(m_camera_tag.is_valid());
1135 const mi::math::Vector<mi::Uint32,2> buffer_resolution(512, 512);
1136 m_image_file_canvas->set_resolution(buffer_resolution);
1137
1138 // Define a region of interest for the entire scene in the
1139 // scene's global coordinate system.
1140 const mi::math::Bbox<mi::Float32, 3> region_of_interest(
1141 0.f, 0.f, 0.f,
1142 static_cast< mi::Float32 >(heightfield_size.x),
1143 static_cast< mi::Float32 >(heightfield_size.y),
1144 static_cast< mi::Float32 >(heightfield_size.x) // Note: using the x dimension to define the z size
1145 );
1146 scene_edit->set_clipped_bounding_box(region_of_interest);
1147
1148 // Finally, optionally adjust the scene's coordinate system
1149 mi::math::Matrix<mi::Float32, 4, 4> transform_mat(
1150 1.0f, 0.0f, 0.0f, 0.0f,
1151 0.0f, 1.0f, 0.0f, 0.0f,
1152 0.0f, 0.0f, -1.0f, 0.0f, // adjust for coordinate system
1153 0.0f, 0.0f, 0.0f, 1.0f
1154 );
1155
1156 scene_edit->set_transform_matrix(transform_mat);
1157
1158 // ... and add the camera to the scene.
1159 scene_edit->set_camera(m_camera_tag);
1160}
1161
1162//----------------------------------------------------------------------
1163bool Multi_view_heightfield::setup_main_host()
1164{
1165 // Access the IndeX rendering query interface for querying performance values and pick results
1166 m_cluster_configuration =
1167 get_index_interface()->get_api_component<nv::index::ICluster_configuration>();
1168 check_success(m_cluster_configuration.is_valid_interface());
1169
1170 // create image canvas in application_layer
1171 m_image_file_canvas = create_image_file_canvas(get_application_layer_interface());
1172 check_success(m_image_file_canvas.is_valid_interface());
1173
1174 // Verifying that local host has joined
1175 // This may fail when there is a license problem.
1176 check_success(is_local_host_joined(m_cluster_configuration.get()));
1177
1178 // DiCE database access
1179 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
1180 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
1181 check_success(dice_transaction.is_valid_interface());
1182 {
1183 //----------------------------------------------------------------------
1184 // Setup session information
1185 m_session_tag =
1186 m_index_session->create_session(dice_transaction.get());
1187 check_success(m_session_tag.is_valid());
1188 mi::base::Handle<const nv::index::ISession> session(
1189 dice_transaction->access<nv::index::ISession>(
1190 m_session_tag));
1191 check_success(session.is_valid_interface());
1192
1193 // Setup the main multiple views, but it is empty.
1194 m_viewport_list = session->create_viewport_list();
1195 check_success(m_viewport_list.is_valid_interface());
1196
1197 //----------------------------------------------------------------------
1198 // Scene setup in the global scope
1199 setup_scene(dice_transaction.get());
1200 }
1201 dice_transaction->commit();
1202
1203 // set canvas size
1204 m_image_file_canvas->set_resolution(mi::math::Vector<mi::Uint32, 2>(512, 512));
1205
1206 INFO_LOG << "Initialization complete.";
1207
1208 return true;
1209}
1210
1211//----------------------------------------------------------------------
1212void Multi_view_heightfield::print_pick_results(
1213 nv::index::IScene_pick_results* scene_pick_results) const
1214{
1215 assert(scene_pick_results != 0);
1216 const mi::Uint32 nb_results = scene_pick_results->get_nb_results();
1217 if (nb_results > 0)
1218 {
1219 INFO_LOG << "Number of pick results: " << nb_results << " on viewport: "
1220 << scene_pick_results->get_viewport_index();
1221 for (mi::Uint32 i = 0; i < nb_results; i++)
1222 {
1223 // Generic information
1224 const mi::base::Handle<nv::index::IScene_pick_result> result(scene_pick_results->get_result(i));
1225
1226 std::stringstream log_out;
1227 log_out << "Intersection no. " << i << "\n"
1228 << "\t\t Element (tag) " << result->get_scene_element().id << "\n"
1229 << "\t\t Sub index: " << result->get_scene_element_sub_index() << "\n"
1230 << "\t\t Distance: " << result->get_distance() << "\n"
1231 << "\t\t Position (local space): " << result->get_intersection() << "\n"
1232 << "\t\t Color (evaluated): " << result->get_color() << "\n";
1233
1234 const mi::base::Handle<const nv::index::IData_sample> data_sample(result->get_data_sample());
1235 if (data_sample)
1236 {
1237 const mi::base::Handle<const nv::index::IData_sample_uint8> ds_uint8(data_sample->get_interface<const nv::index::IData_sample_uint8>());
1238 const mi::base::Handle<const nv::index::IData_sample_uint16> ds_uint16(data_sample->get_interface<const nv::index::IData_sample_uint16>());
1239 const mi::base::Handle<const nv::index::IData_sample_float32> ds_float32(data_sample->get_interface<const nv::index::IData_sample_float32>());
1240 const mi::base::Handle<const nv::index::IData_sample_rgba8> ds_rgba8(data_sample->get_interface<const nv::index::IData_sample_rgba8>());
1241 if (ds_uint8)
1242 {
1243 log_out << "\t Data sample: " << mi::Uint32(ds_uint8->get_sample_value()) << "\n";
1244 }
1245 else if (ds_uint16)
1246 {
1247 log_out << "\t Data sample: " << ds_uint16->get_sample_value() << "\n";
1248 }
1249 else if (ds_float32)
1250 {
1251 log_out << "\t Data sample: " << ds_float32->get_sample_value() << "\n";
1252 }
1253 else if (ds_rgba8)
1254 {
1255 log_out << "\t Data sample: " << ds_rgba8->get_sample_value() << "\n";
1256 }
1257 }
1258
1259 INFO_LOG << log_out.str();
1260
1261 // Shape-specific information
1262 if (result->get_intersection_info_class() == nv::index::IHeightfield_pick_result::IID())
1263 {
1264 mi::base::Handle<const nv::index::IHeightfield_pick_result> compute_pick_result(
1265 result->get_interface<const nv::index::IHeightfield_pick_result>());
1266 if (compute_pick_result && compute_pick_result->is_computing_enabled())
1267 {
1268 INFO_LOG << "Specific pick results for computed heightfield texture:";
1269 INFO_LOG << "\t Computed color value: " << compute_pick_result->get_computed_color();
1270 }
1271 }
1272 }
1273 }
1274 else
1275 {
1276 INFO_LOG << "No pick result.";
1277 }
1278}
1279
1280//----------------------------------------------------------------------
1281bool Multi_view_heightfield::pick_test_call(
1282 const mi::math::Vector<mi::Sint32, 2>& pick_location_on_canvas,
1283 nv::index::IIndex_scene_query* iindex_query,
1284 bool expected_is_hit) const
1285{
1286 assert(iindex_query != 0);
1287 INFO_LOG << "Picking at canvas position: " << pick_location_on_canvas;
1288
1289 mi::base::Handle<nv::index::IViewport_list> cur_viewport_list(
1290 filter_enabled_viewport_index_list());
1291 check_success(cur_viewport_list.is_valid_interface());
1292
1293 // Run the picking operation
1294 mi::base::Handle<nv::index::IScene_pick_results_list> scene_pick_results_list(
1295 iindex_query->pick(pick_location_on_canvas,
1296 m_image_file_canvas.get(),
1297 cur_viewport_list.get(),
1298 m_session_tag));
1299 assert(scene_pick_results_list.is_valid_interface());
1300
1301 const mi::Size nb_list = scene_pick_results_list->size();
1302 mi::Size sum_results = 0;
1303
1304 for (mi::Size i = 0; i < nb_list; ++i)
1305 {
1306 // Print the picking result
1307 mi::base::Handle<nv::index::IScene_pick_results> scene_pick_results(
1308 scene_pick_results_list->get(i));
1309 print_pick_results(scene_pick_results.get());
1310 sum_results += scene_pick_results->get_nb_results();
1311 }
1312
1313 if ((sum_results > 0) != expected_is_hit)
1314 {
1315 INFO_LOG << "expected_is_hit: " << expected_is_hit << ", but sum_results: " << sum_results;
1316 return false;
1317 }
1318
1319 return true;
1320}
1321
1322//----------------------------------------------------------------------
1323// This example shows how to use multi-view functionality with a heightfield
1324int main(int argc, const char* argv[])
1325{
1326 nv::index::app::String_dict sdict;
1327 sdict.insert("dice::verbose", "4"); // log level
1328 sdict.insert("outfname", "frame_multi_view_heightfield"); // output file base name
1329 sdict.insert("verify_image_path_base", ""); // for unit test
1330 sdict.insert("unittest", "0"); // unit test mode
1331 sdict.insert("enable_vidx_vec", "1 1 1 1"); // enabled view indices vector
1332
1333 // Load IndeX library via Index_connect
1334 sdict.insert("dice::network::mode", "OFF");
1335
1336 // index setting
1337 sdict.insert("index::config::set_monitor_performance_values", "true");
1338 sdict.insert("index::service", "rendering_and_compositing");
1339 sdict.insert("index::cuda_debug_checks", "false");
1340
1341 // application_layer component loading
1342 sdict.insert("index::app::components::application_layer::component_name_list",
1343 "canvas_infrastructure image io data_analysis_and_processing");
1344 sdict.insert("index::app::plugins::base_importer::enabled", "true");
1345 sdict.insert("index::app::plugins::legacy_importer::enabled", "true");
1346
1347 // Initialize application
1348 Multi_view_heightfield multi_view_heightfield;
1349 multi_view_heightfield.initialize(argc, argv, sdict);
1350 check_success(multi_view_heightfield.is_initialized());
1351
1352 // launch the application. creating the scene and rendering.
1353 const mi::Sint32 exit_code = multi_view_heightfield.launch();
1354 INFO_LOG << "Shutting down ...";
1355
1356 return exit_code;
1357}
virtual bool evaluate_options(nv::index::app::String_dict &sdict) CPP11_OVERRIDE
virtual bool initialize_networking(mi::neuraylib::INetwork_configuration *network_configuration, nv::index::app::String_dict &options) CPP11_OVERRIDE
int main(int argc, const char *argv[])
#define check_success(expr)