NVIDIA Index example code nvidia_logo_transpbg.gif Up
intersection_highlighting_trianglemesh.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 <sstream>
13
14#include <nv/index/iindex.h>
15#include <nv/index/icamera.h>
16#include <nv/index/iconfig_settings.h>
17#include <nv/index/iintersection_highlighting.h>
18#include <nv/index/iintersection_highlight_pick_result.h>
19#include <nv/index/ilight.h>
20#include <nv/index/imaterial.h>
21#include <nv/index/iplane.h>
22#include <nv/index/iplane_pick_result.h>
23#include <nv/index/itriangle_mesh_scene_element.h>
24#include <nv/index/itriangle_mesh_query_results.h>
25#include <nv/index/iscene.h>
26#include <nv/index/iscene_group.h>
27#include <nv/index/isession.h>
28#include <nv/index/icolormap.h>
29#include <nv/index/itexture.h>
30#include <nv/index/ishading_model.h>
31#include <nv/index/itexture_filter_mode.h>
32
33#include <nv/index/app/idata_analysis_and_processing.h>
34#include <nv/index/app/index_connect.h>
35#include <nv/index/app/string_dict.h>
36
37#include "utility/app_rendering_context.h"
38#include "utility/canvas_utility.h"
39
40//----------------------------------------------------------------------
42 public nv::index::app::Index_connect
43{
44public:
46 :
47 Index_connect()
48 {
49 // INFO_LOG << "DEBUG: Intersection_highlighting_trianglemesh() ctor";
50 }
51
53 {
54 // Note: Index_connect::~Index_connect() will be called after here.
55 // INFO_LOG << "DEBUG: ~Intersection_highlighting_trianglemesh() dtor";
56 }
57
58 // launch application
59 mi::Sint32 launch();
60
61protected:
62 virtual bool evaluate_options(nv::index::app::String_dict& sdict) CPP11_OVERRIDE;
63 // override
65 mi::neuraylib::INetwork_configuration* network_configuration,
66 nv::index::app::String_dict& options) CPP11_OVERRIDE
67 {
68 check_success(network_configuration != 0);
69
70 check_success(options.is_defined("unittest"));
71 const bool is_unittest = nv::index::app::get_bool(options.get("unittest"));
72 if (is_unittest)
73 {
74 info_cout("NETWORK: disabled networking mode.", options);
75 network_configuration->set_mode(mi::neuraylib::INetwork_configuration::MODE_OFF);
76 return true;
77 }
78
79 return initialize_networking_as_default_udp(network_configuration, options);
80 }
81
82private:
83 // Create the scene with a triangle mesh.
84 //
85 // \param[in] mesh_file_0 a triangle mesh file name 0.
86 // \param[in] mesh_bbox_0 bounding box of the mesh, this is also needed for the view computation 0.
87 // \param[in] mesh_file_1 a triangle mesh file name 1.
88 // \param[in] mesh_bbox_1 bounding box of the mesh, this is also needed for the view computation 1.
89 // \param[in] scene_edit IScene
90 // \param[in] dice_transaction dice transaction
91 // \return true when success
92 bool create_scene(
93 const std::string& mesh_file_0,
94 const mi::math::Bbox<mi::Float32, 3>& mesh_bbox_0,
95 const std::string& mesh_file_1,
96 const mi::math::Bbox<mi::Float32, 3>& mesh_bbox_1,
97 nv::index::IScene* scene_edit,
98 mi::neuraylib::IDice_transaction* dice_transaction);
99 // setup camera to see this example scene
100 // \param[in] cam a camera
101 void setup_camera(nv::index::IPerspective_camera* cam) const;
102 void view_all_bbox(
103 const mi::math::Vector<mi::Float32, 3>& from,
104 const mi::math::Vector<mi::Float32, 3>& up,
105 const mi::math::Bbox< mi::Float32, 3 >& bbox,
106 const mi::neuraylib::Tag& camera_tag,
107 const mi::neuraylib::Tag& scene_tag,
108 mi::neuraylib::IDice_transaction* dice_transaction) const;
109 // setup a far away camera for a extreme transformation handling test
110 // See Bugzilla 11567
111 // \param[in] cam a camera
112 void setup_extreme_transformed_camera(nv::index::IPerspective_camera* cam) const;
113 // setup a large scene transform for the extreme
114 // transformation handling test
115 // See Bugzilla 11567
116 mi::math::Matrix<mi::Float32, 4, 4> get_extreme_transformed_matrix() const;
117 // render a frame
118 // \param[in] output_fname output rendering image filename
119 // \return performance values
120 nv::index::IFrame_results* render_frame(const std::string& output_fname) const;
121
122 // This session tag
123 mi::neuraylib::Tag m_session_tag;
124 // NVIDIA IndeX cluster configuration
125 mi::base::Handle<nv::index::ICluster_configuration> m_cluster_configuration;
126 // Application layer image file canvas (a render target)
127 mi::base::Handle<nv::index::app::canvas_infrastructure::IIndex_image_file_canvas> m_image_file_canvas;
128 // Create_icons options
129 std::string m_outfname;
130 bool m_is_unittest;
131 std::string m_verify_image_fname;
132 std::string m_mesh_file_0;
133 std::string m_mesh_file_1;
134 mi::math::Bbox<mi::Float32, 3> m_roi_0;
135 mi::math::Bbox<mi::Float32, 3> m_roi_1;
136 bool m_supersampling;
137 bool m_is_large_translate;
138 mi::Float32 m_mesh_mat_opacity;
139 bool m_mesh_set_pickable;
140};
141
142//----------------------------------------------------------------------
144{
145 mi::Sint32 exit_code = 0;
146
147 // Get DiCE database components
148 {
149 m_cluster_configuration =
150 get_index_interface()->get_api_component<nv::index::ICluster_configuration>();
151 check_success(m_cluster_configuration.is_valid_interface());
152
153 // create image canvas in application_layer
154 m_image_file_canvas = create_image_file_canvas(get_application_layer_interface());
155 check_success(m_image_file_canvas.is_valid_interface());
156
157 mi::base::Handle<nv::index::IIndex_scene_query> iindex_query(
158 get_index_interface()->get_api_component<nv::index::IIndex_scene_query>());
159 check_success(iindex_query.is_valid_interface());
160
161 // Verifying that local host has joined. This may fail when there is a license problem.
162 check_success(is_local_host_joined(m_cluster_configuration.get()));
163
164 {
165 // DiCE database access
166 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
167 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
168 check_success(dice_transaction.is_valid_interface());
169 {
170 // Setup session information
171 m_session_tag = m_index_session->create_session(dice_transaction.get());
172 check_success(m_session_tag.is_valid());
173 mi::base::Handle<const nv::index::ISession> session(
174 dice_transaction->access<const nv::index::ISession>(m_session_tag));
175 check_success(session.is_valid_interface());
176
177 mi::base::Handle< nv::index::IScene > scene_edit(
178 dice_transaction->edit<nv::index::IScene>(session->get_scene()));
179 check_success(scene_edit.is_valid_interface());
180
181 // Enable supersampling
182 if (m_supersampling)
183 {
184 mi::base::Handle<nv::index::IConfig_settings> config_settings(
185 dice_transaction->edit<nv::index::IConfig_settings>(session->get_config()));
186 check_success(config_settings.is_valid_interface());
187
188 config_settings->set_rendering_samples(8);
189 }
190
191 //----------------------------------------------------------------------
192 // Scene setup: hierarchical scene description root node,
193 // scene parameters, camera.
194 //----------------------------------------------------------------------
195 // Create a hierarchical scene description that contains the triangle mesh
196 check_success(create_scene(m_mesh_file_0, m_roi_0, m_mesh_file_1, m_roi_1,
197 scene_edit.get(), dice_transaction.get()));
198
199 // Create and edit a camera. Data distribution is based on
200 // the camera. (Because only visible massive data are
201 // considered)
202 mi::base::Handle< nv::index::IPerspective_camera > cam(
203 scene_edit->create_camera<nv::index::IPerspective_camera>());
204 check_success(cam.is_valid_interface());
205
206 mi::math::Vector<mi::Uint32, 2> buffer_resolution(1024, 1024);
207 if (m_is_large_translate)
208 {
209 INFO_LOG << "large translate test mode.";
210 setup_extreme_transformed_camera(cam.get());
211 buffer_resolution = mi::math::Vector<mi::Uint32, 2>(1602, 934);
212 }
213 else
214 {
215 setup_camera(cam.get());
216 }
217 const mi::neuraylib::Tag camera_tag = dice_transaction->store(cam.get());
218 check_success(camera_tag.is_valid());
219
220 m_image_file_canvas->set_resolution(buffer_resolution);
221
222 // Set up the scene
223 const mi::math::Bbox< mi::Float32, 3 > xyz_roi_st = m_roi_0;
224 // scope for scene edit
225 {
226 mi::base::Handle< nv::index::IScene > scene(
227 dice_transaction->edit< nv::index::IScene >(session->get_scene()));
228 check_success(scene.is_valid_interface());
229
230 // Set the region of interest.
231 const mi::math::Bbox< mi::Float32, 3 > xyz_roi(xyz_roi_st);
232 check_success(xyz_roi.is_volume());
233 scene->set_clipped_bounding_box(xyz_roi_st);
234
235 // Set the scene global transformation matrix.
236 mi::math::Matrix<mi::Float32, 4, 4> transform_mat(1.f);
237 mi::math::Matrix<mi::Float32, 4, 4> scale_mat(1.0f);
238 scale_mat.zz = -0.2f;
239 transform_mat.rotate(0.0f, static_cast<mi::Float32>(M_PI), 0.0f);
240 transform_mat *= scale_mat;
241
242 if(m_is_large_translate)
243 {
244 transform_mat = get_extreme_transformed_matrix();
245 }
246
247 scene->set_transform_matrix(transform_mat);
248
249 // Set the current camera to the scene.
250 check_success(camera_tag.is_valid());
251 scene->set_camera(camera_tag);
252 }
253
254 const mi::math::Vector<mi::Float32, 3> from(0.0f, 0.0f, 1.0f);
255 const mi::math::Vector<mi::Float32, 3> up (0.0f, 1.0f, 0.0f);
256 view_all_bbox(from, up, xyz_roi_st, camera_tag, session->get_scene(), dice_transaction.get());
257 }
258 dice_transaction->commit();
259 }
260
261 // Rendering
262 {
263 // Render a frame and save the rendered image to a file.
264 const mi::Sint32 frame_idx = 0;
265 const std::string fname = get_output_file_name(m_outfname, frame_idx);
266
267 mi::base::Handle<nv::index::IFrame_results> frame_results(render_frame(fname));
268 const mi::base::Handle<nv::index::IError_set> err_set(frame_results->get_error_set());
269 if (err_set->any_errors())
270 {
271 std::ostringstream os;
272 const mi::Uint32 nb_err = err_set->get_nb_errors();
273 for (mi::Uint32 e = 0; e < nb_err; ++e)
274 {
275 if (e != 0) os << '\n';
276 const mi::base::Handle<nv::index::IError> err(err_set->get_error(e));
277 os << err->get_error_string();
278 }
279
280 ERROR_LOG << "IIndex_rendering rendering call failed with the following error(s): " << '\n'
281 << os.str();
282 exit_code = 1;
283 }
284
285 // verify the generated frame
286 if (!(verify_canvas_result(get_application_layer_interface(),
287 m_image_file_canvas.get(), m_verify_image_fname, get_options())))
288 {
289 exit_code = 1;
290 }
291 }
292
293 // Picking
294 {
295 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
296 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
297 check_success(dice_transaction.is_valid_interface());
298 {
299 // Picking
300 mi::math::Vector<mi::Uint32, 2> pick_location(769, 648);
301 mi::base::Handle<nv::index::IScene_pick_results> scene_pick_results(
302 iindex_query->pick(pick_location, m_image_file_canvas.get(), m_session_tag, dice_transaction.get()));
303
304 const mi::Uint32 nb_results = scene_pick_results->get_nb_results();
305 if(nb_results>0)
306 {
307 INFO_LOG << "Number of pick results: " << nb_results;
308 for(mi::Uint32 i=0; i<nb_results; ++i)
309 {
310 const mi::base::Handle<nv::index::IScene_pick_result> result(scene_pick_results->get_result(i));
311 const mi::math::Vector_struct<mi::Float32, 3>& intersection = result->get_intersection();
312 INFO_LOG << "Intersection no. " << i << "\n"
313 << "\t\t Element (tag) " << result->get_scene_element().id << "\n"
314 << "\t\t Sub index: " << result->get_scene_element_sub_index() << "\n"
315 << "\t\t Distance: " << result->get_distance() << "\n"
316 << "\t\t Position (local space): " << intersection << "\n"
317 << "\t\t Color (evaluated): " << result->get_color();
318
319 mi::Sint64 triangle_index = -1;
320 if(result->get_intersection_info_class() == nv::index::ITriangle_mesh_pick_result::IID() )
321 {
322 mi::base::Handle<const nv::index::ITriangle_mesh_pick_result> tri_mesh_pick_result(
323 result->get_interface<const nv::index::ITriangle_mesh_pick_result>());
324 if(tri_mesh_pick_result.get())
325 {
326 triangle_index = static_cast<mi::Sint64>(tri_mesh_pick_result->get_triangle_index());
327 INFO_LOG << "Triangle mesh specific pick results:" << "\n"
328 << "\t\t Triangle id: " << tri_mesh_pick_result->get_triangle_index() << "\n"
329 << "\t\t Local triangle id: " << tri_mesh_pick_result->get_local_triangle_index() << "\n"
330 << "\t\t Normal: " << tri_mesh_pick_result->get_normal() << "\n"
331 << "\t\t Color: " << tri_mesh_pick_result->get_color_value() << "\n"
332 << "\t\t Colormap color: " << tri_mesh_pick_result->get_colormap_value() << "\n"
333 << "\t\t Barycentric coordinate: " << tri_mesh_pick_result->get_barycentric_coordinates();
334 }
335 }
336 if(result->get_intersection_info_class() == nv::index::IIntersection_highlight_pick_result::IID() )
337 {
338 mi::base::Handle<const nv::index::IIntersection_highlight_pick_result> highlight_pick_result(
339 result->get_interface<const nv::index::IIntersection_highlight_pick_result>());
340 if(highlight_pick_result.get())
341 {
342 INFO_LOG << "Intersection highlight specific pick results:" << "\n"
343 << "\t Intersection shape: " << highlight_pick_result->get_intersection_shape();
344 }
345 }
346 if(result->get_intersection_info_class() == nv::index::IPlane_pick_result::IID() )
347 {
348 mi::base::Handle<const nv::index::IPlane_pick_result> compute_pick_result(
349 result->get_interface<const nv::index::IPlane_pick_result>());
350 if(compute_pick_result.get())
351 {
352 INFO_LOG << "Compute plane specific pick results:" << "\n"
353 << "\t Texture color values: " << compute_pick_result->get_texture_color();
354 }
355 }
356
357 // Valid triangle intersection, now query the triangle's details.
358 if(triangle_index>-1)
359 {
360 INFO_LOG << "Query the triangle details for triangle id: " << triangle_index << ".";
361 // Query trinagle details
362 mi::base::Handle<nv::index::IScene_lookup_result> entry_lookup_result(
363 iindex_query->entry_lookup(
364 static_cast<mi::Uint64>(triangle_index), // The global triangle index used to query the triangle's details.
365 result->get_scene_element(), // The tag that represents the triangle scene element.
366 m_session_tag, dice_transaction.get()));
367
368 mi::base::Handle<const nv::index::ITriangle_mesh_lookup_result> tri_mesh_lookup_result(
369 entry_lookup_result->get_interface<const nv::index::ITriangle_mesh_lookup_result>());
370 if(tri_mesh_lookup_result.get())
371 {
372 INFO_LOG << "Receiving the following per-vertex attributes:";
373 mi::math::Vector_struct<mi::Float32, 3> v0;
374 mi::math::Vector_struct<mi::Float32, 3> v1;
375 mi::math::Vector_struct<mi::Float32, 3> v2;
376 tri_mesh_lookup_result->get_vertices(v0, v1, v2);
377 INFO_LOG << "\tVertices: (" << v0 << ',' << v1 << ',' << v2 << ')';
378
379 tri_mesh_lookup_result->get_normals(v0, v1, v2);
380 INFO_LOG << "\tNormals: (" << v0 << ',' << v1 << ',' << v2 << ')';
381
382 mi::math::Vector_struct<mi::Float32, 2> st0;
383 mi::math::Vector_struct<mi::Float32, 2> st1;
384 mi::math::Vector_struct<mi::Float32, 2> st2;
385 tri_mesh_lookup_result->get_texture_coordinates(st0, st1, st2);
386 INFO_LOG << "\tTexture coordinates: (" << st0 << ',' << st1 << ',' << st2 << ')';
387
388 mi::math::Color_struct c0;
389 mi::math::Color_struct c1;
390 mi::math::Color_struct c2;
391 tri_mesh_lookup_result->get_colors(c0, c1, c2);
392 INFO_LOG << "\tColors: (" << c0 << ',' << c1 << ',' << c2 << ')';
393
394 mi::Uint32 cm0, cm1, cm2;
395 tri_mesh_lookup_result->get_color_indices(cm0, cm1, cm2);
396 INFO_LOG << "\tColor index values: (" << cm0 << ',' << cm1 << ',' << cm2 << ')';
397 }
398 }
399 }
400 }
401 }
402
403 // Finish this transaction
404 dice_transaction->commit();
405 }
406 }
407 return exit_code;
408}
409
410//----------------------------------------------------------------------
411bool Intersection_highlighting_trianglemesh::evaluate_options(nv::index::app::String_dict& sdict)
412{
413 const std::string com_name = sdict.get("command:", "<unknown_command>");
414 m_is_unittest = nv::index::app::get_bool(sdict.get("unittest", "false"));
415
416 if (m_is_unittest)
417 {
418 if (nv::index::app::get_bool(sdict.get("is_call_from_test", "false")))
419 {
420 sdict.insert("is_dump_comparison_image_when_failed", "0");
421 }
422 sdict.insert("outfname", ""); // turn off file output in the unit test mode
423 sdict.insert("dice::verbose", "2");
424 }
425
426 m_outfname = sdict.get("outfname");
427 m_verify_image_fname = sdict.get("verify_image_fname");
428 m_mesh_file_0 = sdict.get("mesh_file_0");
429 m_mesh_file_1 = sdict.get("mesh_file_1");
430 m_roi_0 = nv::index::app::get_bbox_from_string<mi::Float32,3>(sdict.get("roi_0"));
431 m_roi_1 = nv::index::app::get_bbox_from_string<mi::Float32,3>(sdict.get("roi_1"));
432 m_supersampling = nv::index::app::get_bool(sdict.get("supersampling", "false"));
433 m_is_large_translate = nv::index::app::get_bool(sdict.get("is_large_translate", "false"));
434 m_mesh_mat_opacity = nv::index::app::get_float32(sdict.get("mesh_mat_opacity"));
435 m_mesh_set_pickable = nv::index::app::get_bool(sdict.get("mesh_set_pickable", "false"));
436
437 info_cout(std::string("running ") + com_name, sdict);
438 info_cout(std::string("outfname = [") + m_outfname +
439 "], verify_image_fname = [" + m_verify_image_fname +
440 "], dice::verbose = " + sdict.get("dice::verbose"), sdict);
441
442 // print help and exit if -h
443 if(sdict.is_defined("h"))
444 {
445 INFO_LOG
446 << "info: Usage: " << com_name << " [option]\n"
447 << "Option: [-h]\n"
448 << " printout this message\n"
449
450 << " [-dice::verbose severity_level]\n"
451 << " verbose severity level (3 is info.). (default: " + sdict.get("dice::verbose")
452 << ")\n"
453
454 << " [-mesh_file_0 string]\n"
455 << " name of a triangle mesh file (in .bin-format). When empty, the default triangle mesh file will be used.\n"
456 << " (default: [" << m_mesh_file_0 << "])\n"
457
458 << " [-mesh_file_1 string]\n"
459 << " name of a triangle mesh file (in .bin-format). When empty, the default triangle mesh file will be used.\n"
460 << " (default: [" << m_mesh_file_1 << "])\n"
461
462 << " [-roi_0 \"float float float float float float\"]\n"
463 << " the bounding box representing the region of interest (roi) for mesh_file_0.\n"
464 << " (default: [" << m_roi_0 << "])\n"
465
466 << " [-roi_1 \"float float float float float float\"]\n"
467 << " the bounding box representing the region of interest (roi) for mesh_file_1.\n"
468 << " (default: [" << m_roi_1 << "])\n"
469
470 << " [-outfname string]\n"
471 << " name of the output ppm image file. When empty, no image file will be written.\n"
472 << " A frame number and the extension (.ppm) will be added.\n"
473 << " (default: [" << m_outfname << "])\n"
474
475 << " [-verify_image_fname [image_fname]]\n"
476 << " when image_fname exist, verify the rendering image. (default: ["
477 << m_verify_image_fname << "])\n"
478
479 << " [-supersampling bool]\n"
480 << " when true then supersampling is enabled."
481 << " (default: " << m_supersampling << ")\n"
482
483 << " [-is_large_translate bool]\n"
484 << " on/off large translation mode."
485 << "(default: " << m_is_large_translate << ")\n"
486
487 << " [-mesh_mat_opacity float]\n"
488 << " mesh material opacity."
489 << "(default: " << m_mesh_mat_opacity << ")\n"
490
491 << " [-mesh_set_pickable bool]\n"
492 << " enable/disable picking for the mesh."
493 << "(default: " << m_mesh_set_pickable << ")\n"
494
495 << " [-unittest bool]\n"
496 << " when true, unit test mode."
497 << " (default: " << m_is_unittest << ")"
498 << std::endl;
499 exit(1);
500 }
501 return true;
502}
503
504//----------------------------------------------------------------------
505bool Intersection_highlighting_trianglemesh::create_scene(
506 const std::string& mesh_file_0,
507 const mi::math::Bbox<mi::Float32, 3>& mesh_bbox_0,
508 const std::string& mesh_file_1,
509 const mi::math::Bbox<mi::Float32, 3>& mesh_bbox_1,
510 nv::index::IScene* scene_edit,
511 mi::neuraylib::IDice_transaction* dice_transaction)
512{
513 check_success(dice_transaction != 0);
514
515 {
516 // Set the default light source
517 mi::base::Handle<nv::index::IDirectional_headlight> headlight(
518 scene_edit->create_attribute<nv::index::IDirectional_headlight>());
519 check_success(headlight.is_valid_interface());
520 headlight->set_direction(mi::math::Vector<mi::Float32, 3>(0.5f, 0.f, -1.f));
521 const mi::neuraylib::Tag headlight_tag = dice_transaction->store(headlight.get());
522 check_success(headlight_tag.is_valid());
523 scene_edit->append(headlight_tag, dice_transaction);
524
525 // Set the default material
526 mi::base::Handle<nv::index::IPhong_gl> phong_1(scene_edit->create_attribute<nv::index::IPhong_gl>());
527 check_success(phong_1.is_valid_interface());
528 phong_1->set_ambient(mi::math::Color(0.1f, 0.1f, 0.1f, 1.0f));
529 phong_1->set_diffuse(mi::math::Color(0.8f, 0.3f, 0.3f, 1.0f));
530 phong_1->set_specular(mi::math::Color(0.75f, 0.8f, 0.75f, 1.0f));
531 if(m_mesh_mat_opacity < 0.99f)
532 {
533 INFO_LOG << "Material opacity is less than 1.0 (" << m_mesh_mat_opacity << ")";
534 }
535 phong_1->set_opacity(m_mesh_mat_opacity);
536 phong_1->set_shininess(85);
537 const mi::neuraylib::Tag phong_1_tag = dice_transaction->store(phong_1.get());
538 check_success(phong_1_tag.is_valid());
539 scene_edit->append(phong_1_tag, dice_transaction);
540 }
541
542 mi::neuraylib::Tag mesh_tag_0;
543 {
544 // triangle mesh creation parameter
545 nv::index::app::String_dict triangle_mesh_opt;
546 triangle_mesh_opt.insert("args::type", "triangle_mesh");
547 triangle_mesh_opt.insert("args::importer", "nv::index::plugin::base_importer.Triangle_mesh_importer");
548 triangle_mesh_opt.insert("args::input_file", mesh_file_0);
549 std::stringstream sstr;
550 sstr << mesh_bbox_0.min.x << " " << mesh_bbox_0.min.y << " " << mesh_bbox_0.min.z << " "
551 << mesh_bbox_0.max.x << " " << mesh_bbox_0.max.y << " " << mesh_bbox_0.max.z;
552 triangle_mesh_opt.insert("args::bbox", sstr.str());
553 nv::index::IDistributed_data_import_callback* importer_callback =
554 get_importer_from_application_layer(
555 get_application_layer_interface(),
556 "nv::index::plugin::base_importer.Triangle_mesh_importer",
557 triangle_mesh_opt);
558
559 // Create the triangle mesh scene element
560 mi::base::Handle<nv::index::ITriangle_mesh_scene_element> mesh(
561 scene_edit->create_triangle_mesh(mesh_bbox_0, importer_callback, dice_transaction));
562 check_success(mesh != 0);
563
564 // scene element properties
565 mesh->set_enabled(true);
566 //
567 mesh->set_pickable(m_mesh_set_pickable);
568
569 // storing the mesh in the data (base) store
570 mesh_tag_0 = dice_transaction->store_for_reference_counting(mesh.get());
571 check_success(mesh_tag_0.is_valid());
572
573 // Create a static scene group
574 mi::base::Handle<nv::index::IStatic_scene_group> static_group(
575 scene_edit->create_scene_group<nv::index::IStatic_scene_group>());
576 check_success(static_group.is_valid_interface());
577
578 // append mesh to the static scene group
579 static_group->append(mesh_tag_0, dice_transaction);
580
581 mi::neuraylib::Tag static_group_tag = dice_transaction->store(static_group.get());
582 check_success(static_group_tag.is_valid());
583
584 // append the static scene group to the hierachical scene description.
585 scene_edit->append(static_group_tag, dice_transaction);
586 }
587
588 mi::neuraylib::Tag mesh_tag_1;
589 {
590 // triangle mesh creation parameter
591 nv::index::app::String_dict triangle_mesh_opt;
592 triangle_mesh_opt.insert("args::type", "triangle_mesh");
593 triangle_mesh_opt.insert("args::importer", "nv::index::plugin::base_importer.Triangle_mesh_importer");
594 triangle_mesh_opt.insert("args::input_file", mesh_file_1);
595 std::stringstream sstr;
596 sstr << mesh_bbox_1.min.x << " " << mesh_bbox_1.min.y << " " << mesh_bbox_1.min.z << " "
597 << mesh_bbox_1.max.x << " " << mesh_bbox_1.max.y << " " << mesh_bbox_1.max.z;
598 triangle_mesh_opt.insert("args::bbox", sstr.str());
599 nv::index::IDistributed_data_import_callback* importer_callback =
600 get_importer_from_application_layer(
601 get_application_layer_interface(),
602 "nv::index::plugin::base_importer.Triangle_mesh_importer",
603 triangle_mesh_opt);
604
605 // Create the triangle mesh scene element
606 mi::base::Handle<nv::index::ITriangle_mesh_scene_element> mesh(
607 scene_edit->create_triangle_mesh(mesh_bbox_1, importer_callback, dice_transaction));
608 check_success(mesh != 0);
609
610 // scene element properties
611 mesh->set_enabled(false);
612 //
613 mesh->set_pickable(m_mesh_set_pickable);
614
615 // storing the mesh in the data (base) store
616 mesh_tag_1 = dice_transaction->store_for_reference_counting(mesh.get());
617 check_success(mesh_tag_1.is_valid());
618
619 // Create a static scene group
620 mi::base::Handle<nv::index::IStatic_scene_group> static_group(
621 scene_edit->create_scene_group<nv::index::IStatic_scene_group>());
622 check_success(static_group.is_valid_interface());
623
624 // append mesh to the static scene group
625 static_group->append(mesh_tag_1, dice_transaction);
626
627 mi::neuraylib::Tag static_group_tag = dice_transaction->store(static_group.get());
628 check_success(static_group_tag.is_valid());
629
630 // append the static scene group to the hierachical scene description.
631 scene_edit->append(static_group_tag, dice_transaction);
632 }
633
634 {
635 // Highlighting for mesh 0
636 mi::base::Handle<nv::index::IIntersection_highlighting> highlighting_0(scene_edit->create_attribute<nv::index::IIntersection_highlighting>());
637 check_success(highlighting_0.is_valid_interface());
638 highlighting_0->set_intersection_shape(mesh_tag_0);
639 highlighting_0->set_width(12.0f);
640 highlighting_0->set_smoothness(0.5f);
641 highlighting_0->set_color(mi::math::Color(0.0f, 1.0f, 0.5f));
642 mi::neuraylib::Tag highlighting_tag_0 = dice_transaction->store_for_reference_counting(highlighting_0.get());
643 check_success(highlighting_tag_0.is_valid());
644 scene_edit->append(highlighting_tag_0, dice_transaction);
645
646 // Highlighting for mesh 1
647 mi::base::Handle<nv::index::IIntersection_highlighting> highlighting_1(scene_edit->create_attribute<nv::index::IIntersection_highlighting>());
648 check_success(highlighting_1.is_valid_interface());
649 highlighting_1->set_intersection_shape(mesh_tag_1);
650 highlighting_1->set_width(20.0f);
651 highlighting_1->set_smoothness(0.5f);
652 highlighting_1->set_color(mi::math::Color(0.0f, 0.5f, 1.0f));
653 mi::neuraylib::Tag highlighting_tag_1 = dice_transaction->store_for_reference_counting(highlighting_1.get());
654 check_success(highlighting_tag_1.is_valid());
655 scene_edit->append(highlighting_tag_1, dice_transaction);
656
657 // Mapping technique: checkerboard
658 const mi::math::Vector<mi::Float32, 2> plane_extent(300.f, 3000.f);
659
660 mi::base::Handle<nv::index::ITexture_filter_mode> tex_filter(
661 scene_edit->create_attribute<nv::index::ITexture_filter_mode_nearest_neighbor>());
662 check_success(tex_filter.is_valid_interface());
663 mi::neuraylib::Tag tex_filter_tag = dice_transaction->store_for_reference_counting(tex_filter.get());
664 check_success(tex_filter_tag.is_valid());
665 scene_edit->append(tex_filter_tag, dice_transaction);
666
667 // Access an application layer component that provides some sample techniques such as the checkerboard for 2d surfaces:
668 mi::base::Handle<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing> processing(
669 get_application_layer_interface()->get_api_component<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing>());
670 check_success(processing.is_valid_interface());
671 // Create a checkerboard technique and add it to the scene. For more details on how to implement the checkerboard, please review the provided
672 // source that was shipped with the application layer component 'nv::index::app::data_analysis_and_processing::IData_analysis_and_processing'.
673 mi::base::Handle<nv::index::IDistributed_compute_technique> mapping(
674 processing->get_sample_tool_set()->create_checker_board_2d_technique(
675 plane_extent,
676 nv::index::IDistributed_compute_destination_buffer_2d_texture::FORMAT_RGBA_FLOAT32,
677 mi::math::Color(0.9f, 0.2f, 0.15f, 0.7f),
678 mi::math::Color(0.2f, 0.2f, 0.8f, 1.0f)));
679
680 mi::neuraylib::Tag mapping_tag = dice_transaction->store_for_reference_counting(mapping.get());
681 check_success(mapping_tag.is_valid());
682 scene_edit->append(mapping_tag, dice_transaction);
683
684 // Plane 0
685 mi::base::Handle<nv::index::IPlane> plane_0(scene_edit->create_shape<nv::index::IPlane>());
686 check_success(plane_0.is_valid_interface());
687 const mi::math::Vector<mi::Float32, 3> plane_point_0(30.f, 30.f, 600.0f);
688 const mi::math::Vector<mi::Float32, 3> plane_normal_0(0.f, 0.f, 1.f);
689 const mi::math::Vector<mi::Float32, 3> plane_up_0(0.f, 1.f, 0.f);
690 plane_0->set_point(plane_point_0);
691 plane_0->set_normal(plane_normal_0);
692 plane_0->set_up(plane_up_0);
693 plane_0->set_extent(plane_extent);
694
695 mi::neuraylib::Tag plane_tag_0 = dice_transaction->store_for_reference_counting(plane_0.get());
696 check_success(plane_tag_0.is_valid());
697 scene_edit->append(plane_tag_0, dice_transaction);
698
699 // Plane 1
700 mi::base::Handle<nv::index::IPlane> plane_1(scene_edit->create_shape<nv::index::IPlane>());
701 check_success(plane_1.is_valid_interface());
702 const mi::math::Vector<mi::Float32, 3> plane_point_1(80.f, 30.f, 760.0f);
703 const mi::math::Vector<mi::Float32, 3> plane_normal_1(1.f, 0.f, 1.f);
704 const mi::math::Vector<mi::Float32, 3> plane_up_1(0.f, 1.f, 0.f);
705 plane_1->set_point(plane_point_1);
706 plane_1->set_normal(plane_normal_1);
707 plane_1->set_up(plane_up_1);
708 plane_1->set_extent(plane_extent);
709
710 mi::neuraylib::Tag plane_tag_1 = dice_transaction->store_for_reference_counting(plane_1.get());
711 check_success(plane_tag_1.is_valid());
712 scene_edit->append(plane_tag_1, dice_transaction);
713 }
714
715 return true;
716}
717
718//----------------------------------------------------------------------
719void Intersection_highlighting_trianglemesh::setup_camera(nv::index::IPerspective_camera* cam) const
720{
721 check_success(cam != 0);
722
723 // Initialize the camera with some default parameters ...
724 const mi::math::Vector< mi::Float32, 3 > from( 0.0f, 0.0f,-5.0f);
725 const mi::math::Vector< mi::Float32, 3 > to ( 0.0f, 0.0f, 0.0f);
726 const mi::math::Vector< mi::Float32, 3 > up ( 0.0f, 1.0f, 0.0f);
727 mi::math::Vector<mi::Float32, 3> viewdir = to - from;
728 viewdir.normalize();
729
730 cam->set(from, viewdir, up);
731 cam->set_aperture(0.033f);
732 cam->set_aspect(1.0f);
733 cam->set_focal(0.03f);
734 cam->set_clip_min(10.0f);
735 cam->set_clip_max(5000.0f);
736}
737
738//----------------------------------------------------------------------
739void Intersection_highlighting_trianglemesh::view_all_bbox(
740 const mi::math::Vector<mi::Float32, 3>& from,
741 const mi::math::Vector<mi::Float32, 3>& up,
742 const mi::math::Bbox< mi::Float32, 3 >& bbox,
743 const mi::neuraylib::Tag& camera_tag,
744 const mi::neuraylib::Tag& scene_tag,
745 mi::neuraylib::IDice_transaction* dice_transaction) const
746{
747 if(bbox.empty())
748 {
749 WARN_LOG << "Un-initialized bounding box and not updating the camera settings.";
750 return;
751 }
752
753 {
754 mi::base::Handle<nv::index::IPerspective_camera> camera(dice_transaction->edit<nv::index::IPerspective_camera>(camera_tag));
755 check_success(camera.is_valid_interface());
756
757 mi::base::Handle<const nv::index::IScene> scene(dice_transaction->access<const nv::index::IScene>(scene_tag));
758 check_success(scene.is_valid_interface());
759
760 // Compute the new camera parameters
761 const mi::math::Bbox< mi::Float32, 3 >& global_roi_bbox = scene->get_clipped_bounding_box();
762 const mi::math::Matrix<mi::Float32, 4, 4>& transform_mat = scene->get_transform_matrix();
763 const mi::math::Vector<mi::Float32, 3> new_min(mi::math::transform_point(transform_mat, global_roi_bbox.min));
764 const mi::math::Vector<mi::Float32, 3> new_max(mi::math::transform_point(transform_mat, global_roi_bbox.max));
765 const mi::math::Bbox< mi::Float32, 3 > transformed_bbox(new_min, new_max);
766 const mi::math::Vector<mi::Float32, 3>& min = transformed_bbox.min;
767 const mi::math::Vector<mi::Float32, 3>& max = transformed_bbox.max;
768 const mi::math::Vector<mi::Float32, 3>& center = transformed_bbox.center();
769 const mi::Float32 rad = mi::math::euclidean_distance(max, min) / 2.0f;
770
771 const mi::Float32 fov_rad_2 = static_cast<mi::Float32>(camera->get_fov_y_rad() / 2.0);
772 const mi::Float32 dist = static_cast<mi::Float32>(rad / tan(fov_rad_2));
773
774 const mi::math::Vector<mi::Float32, 3> eyepos = -(0.7f * dist * from) + center;
775 camera->set_eye_point(eyepos);
776 camera->set_up_direction(up);
777
778 const mi::Float32 clip_min = 0.1f * dist;
779 const mi::Float32 clip_max = 10.0f * 1.f * dist;
780
781 camera->set_clip_min(clip_min);
782 camera->set_clip_max(clip_max);
783 mi::math::Vector<mi::Float32, 3> viewdir = center - eyepos;
784 check_success(viewdir.normalize());
785 camera->set_view_direction(viewdir);
786 }
787}
788
789//----------------------------------------------------------------------
790void Intersection_highlighting_trianglemesh::setup_extreme_transformed_camera(nv::index::IPerspective_camera* cam) const
791{
792 check_success(cam != 0);
793
794 // Adjusted the camera position for p = 23+1.
795 mi::math::Vector< mi::Float32, 3 > const from( 1805060.125f + 8192.0f, 9978520.0f + 16384.0f, 16384.0f);
796 mi::math::Vector< mi::Float32, 3 > const to ( 1805060.125f + 8192.0f, 9978520.0f + 8292.0f, -256.0f);
797 mi::math::Vector< mi::Float32, 3 > const up ( 0.0f, 1.0f, 0.0f);
798 mi::math::Vector<mi::Float32, 3> viewdir = to - from;
799 viewdir.normalize();
800
801 cam->set(from, viewdir, up);
802 cam->set_aperture(0.033f);
803 cam->set_aspect(1.71520f); // not 1.7152034261242f, see IEEE754
804 cam->set_focal(0.03f);
805 cam->set_clip_min(124.485f); // not 124.485130310059f, see IEEE754
806 cam->set_clip_max(17585.6f); // not 17585.55078125f, see IEEE754
807
808 // Note: check affected by view_all or not
809 INFO_LOG << "Set camera extreme mode";
810}
811
812//----------------------------------------------------------------------
813mi::math::Matrix<mi::Float32, 4, 4> Intersection_highlighting_trianglemesh::get_extreme_transformed_matrix() const
814{
815 // transform =
816 // [ 20.6100006103516 0 0 1805060
817 // 0 20.6100006103516 0 9978520
818 // 0 0 -4 0
819 // 0 0 0 1 ]
820
821 mi::math::Matrix<mi::Float32, 4, 4> transform_mat(
822 20.61f, 0.0f, 0.0f, 0.0f,
823 0.0f, 20.61f, 0.0f, 0.0f,
824 0.0f, 0.0f, -4.0f, 0.0f,
825 1805060.0f, 9978520.0f, 0.0f, 1.0f
826 );
827 return transform_mat;
828}
829
830//----------------------------------------------------------------------
831nv::index::IFrame_results* Intersection_highlighting_trianglemesh::render_frame(
832 const std::string& output_fname) const
833{
834 check_success(m_index_rendering.is_valid_interface());
835
836 // set output filename, empty string is valid
837 m_image_file_canvas->set_rgba_file_name(output_fname.c_str());
838
839 check_success(m_session_tag.is_valid());
840
841 mi::base::Handle<mi::neuraylib::IDice_transaction> dice_transaction(
842 m_global_scope->create_transaction<mi::neuraylib::IDice_transaction>());
843 check_success(dice_transaction.is_valid_interface());
844
845 m_index_session->update(m_session_tag, dice_transaction.get());
846
847 mi::base::Handle<nv::index::IFrame_results> frame_results(
848 m_index_rendering->render(
849 m_session_tag,
850 m_image_file_canvas.get(),
851 dice_transaction.get()));
852 check_success(frame_results.is_valid_interface());
853
854 dice_transaction->commit();
855
856 frame_results->retain();
857 return frame_results.get();
858}
859
860//----------------------------------------------------------------------
861// This example shows how to create intersection highlighting on a triangle mesh.
862int main(int argc, const char* argv[])
863{
864 nv::index::app::String_dict sdict;
865 sdict.insert("dice::verbose", "3"); // log level
866 sdict.insert("mesh_file_0", "../intersection_highlighting_trianglemesh/box.ts.bin"); // first triangle mesh
867 sdict.insert("mesh_file_1", "../intersection_highlighting_trianglemesh/box.ts.bin"); // second triangle mesh
868 sdict.insert("highlight_color_0", "0 1 0.5"); // color for intersection highlight 0
869 sdict.insert("highlight_color_1", "0 0.5 1"); // color for intersection highlight 1
870 sdict.insert("roi_0", "0 0 0 330 311 760"); // input roi 0
871 sdict.insert("roi_1", "100 100 127 300 300 611"); // input roi 1
872 sdict.insert("outfname", "frame_intersection_highlighting_trianglemesh"); // output file base name
873 sdict.insert("verify_image_fname", ""); // for unit test
874 sdict.insert("unittest", "0"); // default mode
875 sdict.insert("supersampling", "0"); // disable supersampling (default)
876
877 sdict.insert("is_large_translate", "0"); // large translation mode (default 0)
878 sdict.insert("mesh_mat_opacity", "0.7"); // mesh material opacity (default 1.0, opaque)
879 sdict.insert("mesh_set_pickable", "1"); // define is the mesh shall be pickable
880 sdict.insert("is_dump_comparison_image_when_failed", "1"); // default: dump images when failed.
881 sdict.insert("is_call_from_test", "0"); // default: not call from make check.
882
883 // Load IndeX library via Index_connect
884 sdict.insert("dice::network::mode", "OFF");
885
886 // index setting
887 sdict.insert("index::config::set_monitor_performance_values", "true");
888 sdict.insert("index::service", "rendering_and_compositing");
889 sdict.insert("index::cuda_debug_checks", "false");
890
891 // application_layer component loading
892 sdict.insert("index::app::components::application_layer::component_name_list",
893 "canvas_infrastructure image io data_analysis_and_processing");
894 sdict.insert("index::app::plugins::base_importer::enabled", "true");
895
896 // Initialize application
897 Intersection_highlighting_trianglemesh intersection_highlighting_trianglemesh;
898 intersection_highlighting_trianglemesh.initialize(argc, argv, sdict);
899 check_success(intersection_highlighting_trianglemesh.is_initialized());
900
901 // launch the application. creating the scene and rendering.
902 const mi::Sint32 exit_code = intersection_highlighting_trianglemesh.launch();
903 INFO_LOG << "Shutting down ...";
904
905 return exit_code;
906}
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)