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