NVIDIA Index example code nvidia_logo_transpbg.gif Up
xac_compute_sparse_volume.cpp
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright 2023 NVIDIA Corporation. All rights reserved.
3 *****************************************************************************/
4// Sparse volume setup for xac compute example.
5
8#include <nv/index/isparse_volume_scene_element.h>
9#include <nv/index/isparse_volume_rendering_properties.h>
10
11#include <nv/index/app/forwarding_logger.h>
12#include <nv/index/app/string_dict.h> // get_*
13
15
16namespace xac_compute {
17namespace sparse_volume {
18
19
20static const char* svol_program_begin =
21";NV_IDX_XAC_VERSION_1_0 \n"
22" \n"
23"class Volume_sample_program \n"
24"{ \n"
25" NV_IDX_VOLUME_SAMPLE_PROGRAM \n"
26" \n"
27"public: \n"
28" const nv::index::xac::Colormap colormap = state.self.get_colormap(); \n"
29" \n"
30" NV_IDX_DEVICE_INLINE_MEMBER void initialize() \n"
31" { \n"
32" } \n"
33"\n"
34;
35
36static const char* program_end =
37"}; \n"
38;
39
40static const char* svol_color_program =
41" // The user program used for rendering. \n"
42" NV_IDX_DEVICE_INLINE_MEMBER int execute( \n"
43" const Sample_info_self& sample_info, \n"
44" Sample_output& sample_output) \n"
45" { \n"
46" const auto& svol = state.self; \n"
47" const auto svol_sampler = svol.generate_sampler<float>(0u, \n"
48" sample_info.sample_context); \n"
49" const float v = svol_sampler.fetch_sample( \n"
50" sample_info.sample_position_object_space); \n"
51" sample_output.set_color(colormap.lookup(v)); \n"
52" return NV_IDX_PROG_OK; \n"
53" } \n"
54"\n"
55;
56
57static const char* svol_compute_program =
58" // The user program for compute. \n"
59" NV_IDX_DEVICE_INLINE_MEMBER \n"
60" int compute( \n"
61" const Data_point_info_self& data_point_info, // read-only \n"
62" Data_point_output& data_output) \n"
63" { \n"
64" const unsigned int attr_idx = 0; \n"
65" const auto& vol = state.self; \n"
66" float v = vol.get_attribute<float>(attr_idx, data_point_info); \n"
67" \n"
68" v = 1.f - v * 0.9f; // Modify value v. \n"
69" \n"
70" // Write modified value to data point output. \n"
71" data_output.write_value<float>(attr_idx, v); \n"
72" \n"
73" return NV_IDX_PROG_OK; \n"
74" } \n"
75"\n"
76;
77
78static const char* plane_sample_function =
79" NV_IDX_DEVICE_INLINE_MEMBER bool sample_func( \n"
80" const float3& scene_position, \n"
81" float& sample_value, \n"
82" float4& color) const \n"
83" { \n"
84" // Access the first Sparse_volume available (works only if volume is active) \n"
85" if (state.scene.get_number_of_elements<xac::Sparse_volume>() == 0) { \n"
86" return false; \n"
87" } \n"
88" const xac::Sparse_volume& volume = state.scene.access_by_id<xac::Sparse_volume>(0); \n"
89" \n"
90" if (state.scene.get_number_of_elements<xac::Colormap>() == 0) { \n"
91" return false; \n"
92" } \n"
93" \n"
94" const float3 sample_pos = transform_point(volume.get_scene_to_object_transform(), scene_position); \n"
95" if (!xaclib::is_inside_bounding_box(volume.get_volume_bbox_min(), volume.get_volume_bbox_max(), \n"
96" sample_pos)) \n"
97" { \n"
98" return false; \n"
99" } \n"
100" \n"
101" const uint attr_index = 0u; \n"
102" const auto sampler = volume.generate_sampler<float, \n"
103" xac::Volume_filter_mode::TRILINEAR, xac::Volume_classification_mode::POST_INTERPOLATION>(attr_index); \n"
104" \n"
105" sample_value = sampler.fetch_sample(sample_pos); \n"
106" \n"
107" const xac::Colormap colormap = volume.get_colormap(); \n"
108" color = colormap.lookup(sample_value); \n"
109" \n"
110" return true; \n"
111" } \n"
112"\n"
113;
114
115
116
117
123};
124
125
126
127
128
129#define SVOL_MODEL 1
130/*
131 svol_bucky64_uint8
132
133 opt_map["svol.input_file_base_name"] = "bucky_C60_64_64_64";
134 opt_map["svol.input_directory"] = ".";
135 opt_map["svol.input_file_extension"] = ".vol";
136 opt_map["svol.size"] = "64 64 64";
137
138 from: -56.44580078125 -1.99575769901276 76.410285949707
139 dir: 0.822186231613159 0.390750795602798 -0.413912683725357
140 up: -0.223093569278717 0.890190124511719 0.397229105234146
141
142 svol_bucky128_uint8
143
144 opt_map["svol.input_file_base_name"] = "bucky_C60Large_128_128_128";
145 opt_map["svol.input_directory"] = ".";
146 opt_map["svol.input_file_extension"] = ".vol";
147 opt_map["svol.size"] = "128 128 128";
148 'from': '-112.29296875 -7.79020595550537 154.107467651367',
149 'dir': '0.822186231613159 0.390750795602798 -0.413912683725357',
150 'up': '-0.223093569278717 0.890190124511719 0.397229105234146',
151*/
152
153
154
155
156void Sparse_volume_setup::register_classes(nv::index::IIndex* index_interface) const
157{
158 // empty
159}
160
161
163{
164#if (SVOL_MODEL == 1)
165 opt_map["svol.input_file_base_name"] = "bucky_C60_64_64_64";
166 opt_map["svol.size"] = "64 64 64";
167#endif
168#if (SVOL_MODEL == 2)
169 opt_map["svol.input_file_base_name"] = "bucky_C60Large_128_128_128";
170 opt_map["svol.size"] = "128 128 128";
171#endif
172 opt_map["svol.input_directory"] = ".";
173 opt_map["svol.input_file_extension"] = ".vol";
174 opt_map["svol.format"] = "uint8";
175 opt_map["svol.ordering"] = "xyz";
176 opt_map["svol.filter_mode"] = "trilinear";
177 opt_map["svol.brick_size"] = "60 60 60";
178 opt_map["svol.brick_border"] = "2";
179 opt_map["svol.preintegration"] = "0";
180 opt_map["svol.lod_render"] = "0";
181 opt_map["svol.show_lod"] = "0";
182}
183
184
186{
187 usage.opt("svol.input_directory", "DIR", "Directory of the input volume.");
188 usage.opt("svol.input_file_base_name", "NAME", "File base-name of the input volume (without extension).");
189 usage.opt("svol.input_file_extension", "EXT", "File extension of the input volume.");
190 usage.opt("svol.format", "FORMAT", "Voxel format (uint8, float32).");
191 usage.opt("svol.size", "X Y Z", "Volume size.");
192 usage.opt("svol.ordering", "NAME", "Input volume axis-ordering (xyz, zyx).");
193 usage.opt("svol.filter_mode", "NAME", "Volume filter (nearest, trilinear).");
194 usage.opt("svol.brick_size", "X Y Z", "Brick size in voxels.");
195 usage.opt("svol.brick_border", "n", "Brick border in voxels.");
196 usage.opt("svol.preintegration", "bool", "Render using the pre-integration-based volume rendering technique.");
197 usage.opt("svol.lod_render", "bool", "Render using the level-of-detail volume rendering technique.");
198 usage.opt("svol.show_lod", "bool", "Show the level-of-detail structure used but the volume rendering technique.");
199}
200
201
203{
204 return "0 0 0 126 126 126";
205}
206
208{
209 std::string input_dir;
210 std::string input_file_base;
211 std::string input_file_ext;
213 mi::neuraylib::Tag svol_element_tag;
214};
215
217 Nvindex_access& nvindex_accessor,
218 Svol_load_info& load_info,
219 const Option_map& opt_map,
220 nv::index::IScene* scene,
221 mi::neuraylib::IDice_transaction* transaction)
222{
223 const Vec3u svol_input_size = nv::index::app::get_vector_from_string<mi::Uint32,3>(opt_map["svol.size"]);
224 const Bbox3f svol_input_bbox(0.0f, 0.0f, 0.0f,
225 static_cast<mi::Float32>(svol_input_size.x),
226 static_cast<mi::Float32>(svol_input_size.y),
227 static_cast<mi::Float32>(svol_input_size.z));
228
229 const Bbox3i svol_bbox_i(
230 static_cast<mi::Sint32>(floorf(svol_input_bbox.min.x)),
231 static_cast<mi::Sint32>(floorf(svol_input_bbox.min.y)),
232 static_cast<mi::Sint32>(floorf(svol_input_bbox.min.z)),
233 static_cast<mi::Sint32>(ceilf(svol_input_bbox.max.x)),
234 static_cast<mi::Sint32>(ceilf(svol_input_bbox.max.y)),
235 static_cast<mi::Sint32>(ceilf(svol_input_bbox.max.z)));
236
237 // sparse volume creation parameter
238 std::map<std::string, std::string> sparse_volume_opt;
239 sparse_volume_opt["type"] = "sparse_volume";
240 sparse_volume_opt["importer"] = "nv::index::plugin::base_importer.Sparse_volume_importer_raw";
241 sparse_volume_opt["input_directory"] = load_info.input_dir;
242 sparse_volume_opt["input_file_base_name"] = load_info.input_file_base;
243 sparse_volume_opt["input_file_extension"] = load_info.input_file_ext;
244 sparse_volume_opt["convert_zyx_to_xyz"] = (opt_map["svol.ordering"] != "xyz" ) ? "true" : "false";
245 sparse_volume_opt["bbox"] = "0 0 0 " + opt_map["svol.size"];
246 sparse_volume_opt["voxel_format"] = opt_map["svol.format"];
247
248 nv::index::IDistributed_data_import_callback* importer_callback =
249 get_importer_from_application_layer(
250 nvindex_accessor.get_application_layer_interface(),
251 "nv::index::plugin::base_importer.Sparse_volume_importer_raw",
252 sparse_volume_opt);
253
254 const mi::math::Matrix<mi::Float32, 4, 4> svol_transform(1.0f);
255 mi::base::Handle<nv::index::ISparse_volume_scene_element> svol_scene_elem(
256 scene->create_sparse_volume(svol_input_bbox, svol_transform, importer_callback, transaction));
257
258 load_info.svol_element_tag = transaction->store_for_reference_counting(svol_scene_elem.get());
259 load_info.svol_bbox_i = svol_bbox_i;
260}
261
262
263
265 Nvindex_access& nvindex_accessor,
266 Scene_info& scene_info,
267 const Bbox3f& roi_bbox,
268 mi::neuraylib::Tag session_tag,
269 const Option_map& opt_map,
270 mi::neuraylib::IDice_transaction* transaction) const
271{
272 Scene_tool scene_tool(session_tag, transaction);
273
274 m_info.svol_group_tag = scene_tool.add_new_group();
275
276 // Create a color map using an external utility function.
277 const mi::Sint32 colormap_entry_id = 41; // same as demo application's colormap file 40 (41)
278 mi::neuraylib::Tag colormap_tag = create_colormap(colormap_entry_id, scene_tool.scene.get(), transaction);
279 check_success(colormap_tag.is_valid());
280
281
282 // Sparse volume scene element/importer
283 Svol_load_info ldinfo;
284 ldinfo.input_dir = opt_map["svol.input_directory"];
285 ldinfo.input_file_base = opt_map["svol.input_file_base_name"];
286 ldinfo.input_file_ext = opt_map["svol.input_file_extension"];
287
288 load_sparse_volume_data(nvindex_accessor, ldinfo, opt_map, scene_tool.scene.get(), transaction);
289 check_success(ldinfo.svol_element_tag.is_valid());
290
293
294
295 // Append the volume sample program before the volume element
296 scene_tool.current_group->append(colormap_tag, transaction);
297
298 add_render_props(opt_map, scene_tool);
299
300 std::pair<mi::neuraylib::Tag, std::string> prg_info = add_user_program(
302 nv::index::app::get_sint32(opt_map["user_program_mode"]),
303 scene_info.rtc_program_source,
305 scene_tool);
306 scene_info.compute_launch_info.compute_program_tag = prg_info.first;
307 scene_info.rtc_program_source = prg_info.second;
309 scene_tool.current_group->append(m_info.svol_element_tag, transaction);
310
311 std::stringstream sstr;
312 sstr << "Created a sparse volume: size = [" << opt_map["svol.size"] << "], tag = " << m_info.svol_element_tag.id;
313 INFO_LOG << sstr.str();
314
315 return true;
316}
317
318//index::camera::eye_point = 130.661270141602 30.0881538391113 79.4874954223633
319//index::camera::view_direction = -0.906582176685333 0.0041832085698843 - 0.422008663415909
320//index::camera::up_direction = 0 1 0
321
323 mi::neuraylib::Tag camera_tag,
324 const Option_map& opt_map,
325 mi::neuraylib::IDice_transaction* transaction) const
326{
327 check_success(camera_tag.is_valid());
328 check_success(transaction != 0);
329 mi::base::Handle<nv::index::IPerspective_camera>
330 cam(transaction->edit<nv::index::IPerspective_camera>(camera_tag));
331 check_success(cam.is_valid_interface());
332
333#if (SVOL_MODEL == 1)
334 Vec3f from(-56.44580078125f, -1.99575769901276f, 76.410285949707f);
335 Vec3f to(0.822186231613159f, 0.390750795602798f, -0.413912683725357f);
336 Vec3f up(-0.223093569278717f, 0.890190124511719f, 0.397229105234146f);
337#endif
338#if (SVOL_MODEL == 2)
339 Vec3f from(-112.29296875f, -7.79020595550537f, 154.107467651367f);
340 Vec3f to(0.822186231613159f, 0.390750795602798f, -0.413912683725357f);
341 Vec3f up(-0.223093569278717f, 0.890190124511719f, 0.397229105234146f);
342#endif
343
344 if (nv::index::app::get_sint32(opt_map["compute_plane"]) != 0) {
345 from = Vec3f(130.661270141602f, 30.0881538391113f, 79.4874954223633f);
346 to = Vec3f(-0.906582176685333f, 0.0041832085698843f, -0.422008663415909f);
347 up = Vec3f(0.f, 1.f, 0.f);
348 }
349
350 Vec3f viewdir = to;// - from;
351 viewdir.normalize();
352
353 cam->set(from, viewdir, up);
354 cam->set_aperture(0.033f);
355 cam->set_focal(0.03f);
356 cam->set_clip_min(0.001f);
357 cam->set_clip_max(1500.0f);
358}
359
360
361
362
363
365 mi::neuraylib::Tag session_tag,
366 const Option_map& opt_map,
367 mi::neuraylib::IDice_transaction* transaction) const
368{
369 std::string svol_export_filename =
370 opt_map["export_directory"] +
371 opt_map["export_file_name"] +
372 opt_map["export_file_ext"];
373 if (svol_export_filename.empty()) {
374 return true;
375 }
376 INFO_LOG << "Exporting sparse volume data to " << svol_export_filename;
380 svol_export_filename,
381 session_tag,
382 transaction))
383 {
384 ERROR_LOG << "Failed to export sparse volume data "
385 << "(volume scene element: " << m_info.svol_element_tag
386 << ", volume export box: " << m_info.svol_element_bbox
387 << ", export file: " << svol_export_filename << ").";
388 return false;
389 }
390
391 return true;
392}
393
394
396 mi::neuraylib::Tag session_tag,
397 const Option_map& opt_map,
398 mi::neuraylib::IDice_transaction* transaction) const
399{
400 // Access the session instance from the database.
401 mi::base::Handle<const nv::index::ISession> session(
402 transaction->access<const nv::index::ISession>(session_tag));
403 check_success(session.is_valid_interface());
404
405 // Access (edit mode) the scene instance from the database.
406 mi::base::Handle<nv::index::IScene> scene(
407 transaction->edit<nv::index::IScene>(session->get_scene()));
408 check_success(scene.is_valid_interface());
409
410 mi::base::Handle<nv::index::IStatic_scene_group> group(
411 transaction->edit<nv::index::IStatic_scene_group>(m_info.svol_group_tag));
412 check_success(group.is_valid_interface());
413
414 group->remove(m_info.svol_element_tag, transaction);
415
416 transaction->remove(m_info.svol_element_tag);
417 m_info.svol_element_tag = mi::neuraylib::Tag();
419}
420
421
423{
424 return true;
425}
426
427
429 Nvindex_access& nvindex_accessor,
430 mi::neuraylib::Tag session_tag,
431 const Option_map& opt_map,
432 mi::neuraylib::IDice_transaction* transaction) const
433{
434 // Access the session instance from the database.
435 mi::base::Handle<const nv::index::ISession> session(
436 transaction->access<const nv::index::ISession>(session_tag));
437 check_success(session.is_valid_interface());
438
439 // Access (edit mode) the scene instance from the database.
440 mi::base::Handle<nv::index::IScene> scene(
441 transaction->edit<nv::index::IScene>(session->get_scene()));
442 check_success(scene.is_valid_interface());
443
444
445 // Sparse volume scene element/importer
446 Svol_load_info ldinfo;
447 ldinfo.input_dir = opt_map["export_directory"];
448 ldinfo.input_file_base = opt_map["export_file_name"];
449 ldinfo.input_file_ext = opt_map["export_file_ext"];
450
451 if (ldinfo.input_dir == "") { ldinfo.input_dir = "."; }
452
453 load_sparse_volume_data(nvindex_accessor, ldinfo, opt_map, scene.get(), transaction);
454 check_success(ldinfo.svol_element_tag.is_valid());
455
458
459 // reconnect to scene group
460 mi::base::Handle<nv::index::IStatic_scene_group> group(
461 transaction->edit<nv::index::IStatic_scene_group>(m_info.svol_group_tag));
462 check_success(group.is_valid_interface());
463
464 group->append(m_info.svol_element_tag, transaction);
465 return true;
466}
467
468
469
471{
472 return true;
473}
474
475
477{
479}
480
481
482void Sparse_volume_setup::add_render_props(
483 const Option_map& opt_map,
484 Scene_tool& scene_tool)
485{
486 // Sparse volume rendering properties
487 mi::base::Handle<nv::index::ISparse_volume_rendering_properties> svol_render_prop;
488 scene_tool.create_attribute(svol_render_prop);
489
490 const std::string filter_mode = opt_map["svol.filter_mode"];
491 if (filter_mode == "nearest") {
492 svol_render_prop->set_filter_mode(nv::index::SPARSE_VOLUME_FILTER_NEAREST);
493 }
494 else if (filter_mode == "trilinear") {
495 svol_render_prop->set_filter_mode(nv::index::SPARSE_VOLUME_FILTER_TRILINEAR_POST);
496 }
497
498 const bool use_preint_render = nv::index::app::get_bool(opt_map["svol.preintegration"]);
499 svol_render_prop->set_preintegrated_volume_rendering(use_preint_render);
500 svol_render_prop->set_voxel_offsets(Vec3f(0.f, 0.f, 0.f));
501
502 const bool use_lod_render = nv::index::app::get_bool(opt_map["svol.lod_render"]);
503 svol_render_prop->set_lod_rendering_enabled(use_lod_render);
504 svol_render_prop->set_lod_pixel_threshold(2.5f);
505
506 const bool show_lod_render = nv::index::app::get_bool(opt_map["svol.show_lod"]);
507 svol_render_prop->set_debug_visualization_option(show_lod_render ? 2u : 0u);
508
509 scene_tool.store_and_add_to_group(svol_render_prop);
510}
511
512
513
514}//sparse_volume
515}//xac_compute
516
void opt(const std::string &opt, const char *arg_info, const char *subline="")
Definition: xac_compute.h:94
bool reload_scene(Nvindex_access &nvindex_accessor, mi::neuraylib::Tag session_tag, const Option_map &opt_map, mi::neuraylib::IDice_transaction *transaction) const
void unload_scene(mi::neuraylib::Tag session_tag, const Option_map &opt_map, mi::neuraylib::IDice_transaction *transaction) const
bool export_scene_data(mi::neuraylib::Tag session_tag, const Option_map &opt_map, mi::neuraylib::IDice_transaction *transaction) const
bool create_scene(Nvindex_access &nvindex_accessor, Scene_info &scene_info, const Bbox3f &roi_bbox, mi::neuraylib::Tag session_tag, const Option_map &opt_map, mi::neuraylib::IDice_transaction *transaction) const
void setup_camera(mi::neuraylib::Tag camera_tag, const Option_map &opt_map, mi::neuraylib::IDice_transaction *transaction) const
void register_classes(nv::index::IIndex *index_interface) const
static const Program_source svol_program
static void load_sparse_volume_data(Nvindex_access &nvindex_accessor, Svol_load_info &load_info, const Option_map &opt_map, nv::index::IScene *scene, mi::neuraylib::IDice_transaction *transaction)
XAC compute example scenes.
Definition: xac_compute.cpp:27
std::pair< mi::neuraylib::Tag, std::string > add_user_program(Sample_program_kind prg_kind, int user_prg, const std::string &user_text, const Program_source &prg_text, Scene_tool &scene_tool, const char *extra_pgr_methods)
mi::math::Bbox< mi::Float32, 3 > Bbox3f
Definition: xac_compute.h:29
mi::math::Vector< mi::Uint32, 3 > Vec3u
Definition: xac_compute.h:36
mi::math::Vector< mi::Float32, 3 > Vec3f
Definition: xac_compute.h:38
mi::math::Bbox< mi::Sint32, 3 > Bbox3i
Definition: xac_compute.h:27
bool export_sparse_volume_data(const mi::neuraylib::Tag &volume_tag, const mi::math::Bbox< mi::Sint32, 3 > &volume_export_bbox, const std::string &volume_export_filename, const mi::neuraylib::Tag &session_tag, mi::neuraylib::IDice_transaction *dice_transaction)
External sparse volume data export function for regular volumes.
#define check_success(expr)
mi::neuraylib::Tag scene_element_tag
Definition: xac_compute.h:130
mi::neuraylib::Tag compute_program_tag
Definition: xac_compute.h:129
std::string rtc_program_source
Definition: xac_compute.h:141
Compute_launch_info compute_launch_info
Definition: xac_compute.h:140
mi::base::Handle< nv::index::IScene_group > current_group
mi::base::Handle< nv::index::IScene > scene
mi::neuraylib::Tag add_new_group(bool transformed_group=false)
mi::neuraylib::Tag store_and_add_to_group(const mi::base::Handle<T> &element)
void create_attribute(mi::base::Handle<T> &element)
Scene setup interface for xac compute example.
Sparse volume setup for xac compute example.