NVIDIA Index example code nvidia_logo_transpbg.gif Up
ray_sampling_lod_heightfield.h
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright 2023 NVIDIA Corporation. All rights reserved.
3 *****************************************************************************/
9#ifndef EXAMPLES_RAY_SAMPLING_LOD_HEIGHTFIELD_H
10#define EXAMPLES_RAY_SAMPLING_LOD_HEIGHTFIELD_H
11
12#include "ray_sampling_scenes.h"
13#include <nv/index/ilight.h>
14#include <nv/index/imaterial.h>
15#include <nv/index/itexture_filter_mode.h>
16#include <nv/index/iregular_heightfield_rendering_properties.h>
17
18// Application layer component
19#include <nv/index/app/idata_analysis_and_processing.h>
20
22
23static const char* program_begin =
24";NV_IDX_XAC_VERSION_1_0 \n"
25" \n"
26"class Surface_sample_program \n"
27"{ \n"
28" NV_IDX_SURFACE_SAMPLE_PROGRAM \n"
29" \n"
30"public: \n"
31" int counter; \n"
32" \n"
33" NV_IDX_DEVICE_INLINE_MEMBER void initialize() \n"
34" { \n"
35" counter = 0; \n"
36" } \n"
37" \n"
38;
39
40static const char* program_end =
41"}; \n"
42;
43
44static const char* color_program =
45" NV_IDX_DEVICE_INLINE_MEMBER int execute( \n"
46" const Sample_info_self& sample_info, \n"
47" Sample_output& sample_output) \n"
48" { \n"
49" const float4& sample_color = sample_info.sample_color; \n"
50" sample_output.set_color(sample_color); \n"
51" return NV_IDX_PROG_OK; \n"
52" } \n"
53;
54
55static const char* inquire_program =
56" // The user program used for picking. \n"
57" NV_IDX_DEVICE_INLINE_MEMBER int inquire( \n"
58" const Sample_info_self& sample_info, \n"
59" Query_results& query_results) \n"
60" { \n"
61" // sample_info.ray_t is automatically written \n"
62" // color is automatically written \n"
63" \n"
64" // we could invalidate current sample to skip/ignore it \n"
65" //query_results.invalidate_sample(); \n"
66" \n"
67" // write some attribute value of current sample \n"
68" const float v = //state.self.sample<float>( \n"
69" sample_info.sample_position.x; \n"
70" query_results.write_value<float>(0u /*user_value_idx*/, v); \n"
71" \n"
72" counter += 1; \n"
73" if (counter & 1) { \n"
74" // write every other counter as user value \n"
75" query_results.write_value<int>(1u /*user_value_idx*/, counter); \n"
76" } \n"
77" \n"
78" const float3 normal = sample_info.sample_normal; \n"
79" query_results.write_value<float3>(2u /*user_value_idx*/, normal); \n"
80" \n"
81" return NV_IDX_PROG_OK; \n"
82" \n"
83" // we can stop sampling: \n"
84" //return NV_IDX_PROG_TERMINATE_PROGRAM_INSTANCE; \n"
85" } \n"
86;
87
88//----------------------------------------------------------------------
89
90
92{
93public:
94 void register_classes(nv::index::IIndex* index_interface) const
95 {
96 }
97
98 void add_arguments(std::map<std::string, std::string>& opt_map) const
99 {
100 opt_map["hfield.texture"] = "height_color"; // texture "none","mandelbrot","height_color"
101 }
102
103 void usage_info(std::ostream& os, const char* indent, std::map<std::string, std::string>& opt_map) const
104 {
105 os << indent << "[-hfield.texture mode]\n"
106 << indent << " map a computed texture onto the heightfield. \n"
107 << indent << " Available modes: none, mandelbrot, height_color \n"
108 << indent << " (default: " << opt_map["hfield.texture"] << ")\n";
109 }
110
111 const char* get_roi_string() const
112 {
113 return "-1000 -1000 -1000 5000 5000 5000";
114 }
115
117 const std::string& texture_type,
118 nv::index::IScene* scene,
119 nv::index::IStatic_scene_group* static_group_node,
120 mi::neuraylib::IDice_transaction* transaction) const
121 {
122 // Add a light
123 mi::base::Handle<nv::index::IDirectional_headlight> headlight(
124 scene->create_attribute<nv::index::IDirectional_headlight>());
125 check_success(headlight.is_valid_interface());
126 const mi::math::Color color_intensity(1.0f, 1.0f, 1.0f, 1.0f);
127 headlight->set_intensity(color_intensity);
128 headlight->set_direction(mi::math::Vector<mi::Float32, 3>(1.0f, -1.0f, -1.0f));
129 const mi::neuraylib::Tag headlight_tag = transaction->store_for_reference_counting(headlight.get());
130 check_success(headlight_tag.is_valid());
131 static_group_node->append(headlight_tag, transaction);
132
133 // Material for the heightfield
134 mi::base::Handle<nv::index::IPhong_gl> phong_1(scene->create_attribute<nv::index::IPhong_gl>());
135 check_success(phong_1.is_valid_interface());
136
137 if (texture_type != "none") {
138 // Use just ambient white with texture
139 phong_1->set_ambient(mi::math::Color(1.f));
140 phong_1->set_diffuse(mi::math::Color(0.f));
141 phong_1->set_specular(mi::math::Color(0.f));
142 }
143 else {
144 // Define a more interesting greenish material
145 phong_1->set_ambient(mi::math::Color(0.f, 0.3f, 0.0f, 0.3f));
146 phong_1->set_diffuse(mi::math::Color(0.f, 0.8f, 0.2f, 0.3f));
147 phong_1->set_specular(mi::math::Color(0.6f));
148 phong_1->set_shininess(100.f);
149 }
150
151 const mi::neuraylib::Tag phong_1_tag
152 = transaction->store_for_reference_counting(phong_1.get());
153 check_success(phong_1_tag.is_valid());
154 static_group_node->append(phong_1_tag, transaction);
155 }
156
158 nv::index::app::IApplication_layer* app_layer,
159 const std::string& texture_type,
160 const mi::math::Bbox<mi::Float32, 3>& heightfield_bbox,
161 nv::index::IScene* scene,
162 nv::index::IStatic_scene_group* static_group_node,
163 mi::neuraylib::IDice_transaction* transaction) const
164 {
165 // Mandelbrot texture
166 if (texture_type == "mandelbrot")
167 {
168 mi::base::Handle<nv::index::ITexture_filter_mode> tex_filter(
169 scene->create_attribute<nv::index::ITexture_filter_mode_nearest_neighbor>());
170 check_success(tex_filter.is_valid_interface());
171 mi::neuraylib::Tag tex_filter_tag = transaction->store_for_reference_counting(tex_filter.get());
172 check_success(tex_filter_tag.is_valid());
173 static_group_node->append(tex_filter_tag, transaction);
174
175
176 mi::base::Handle<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing> processing(
177 app_layer->get_api_component<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing>());
178 check_success(processing.is_valid_interface());
179 // Create a mandelbrot technique and add it to the scene. For more details on how to implement the checkerboard, please review the provided
180 // source that was shipped with the application layer component 'nv::index::app::data_analysis_and_processing::IData_analysis_and_processing'.
181 mi::base::Handle<nv::index::IDistributed_compute_technique> mapping(
182 processing->get_sample_tool_set()->create_mandelbrot_2d_technique(mi::math::Vector<mi::Float32, 2>(1250.f, 680.f)));
183 check_success(mapping.is_valid_interface());
184
185 // Add the mapping to the scene before the heightfield
186 mi::neuraylib::Tag mapping_tag = transaction->store_for_reference_counting(mapping.get());
187 check_success(mapping_tag.is_valid());
188 static_group_node->append(mapping_tag, transaction);
189 }
190 // Map height values in the heightfield to colors
191 else if (texture_type == "height_color")
192 {
193 // Create the computed texture, passing the height range of the heightfield
194 const mi::math::Vector<mi::Float32, 2> height_range(
195 heightfield_bbox.min.z, heightfield_bbox.max.z);
196
197 mi::base::Handle<nv::index::ITexture_filter_mode> tex_filter(
198 scene->create_attribute<nv::index::ITexture_filter_mode_nearest_neighbor>());
199 check_success(tex_filter.is_valid_interface());
200 mi::neuraylib::Tag tex_filter_tag = transaction->store_for_reference_counting(tex_filter.get());
201 check_success(tex_filter_tag.is_valid());
202 static_group_node->append(tex_filter_tag, transaction);
203
204 // Create the computed texture, with a size fitting the heightfield
205 mi::base::Handle<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing> processing(
206 app_layer->get_api_component<nv::index::app::data_analysis_and_processing::IData_analysis_and_processing>());
207 check_success(processing.is_valid_interface());
208 // Create a mandelbrot technique and add it to the scene. For more details on how to implement the checkerboard, please review the provided
209 // source that was shipped with the application layer component 'nv::index::app::data_analysis_and_processing::IData_analysis_and_processing'.
210 const mi::math::Color color0(0.f, 1.f, 0.f, 1.f); // green
211 const mi::math::Color color1(1.f, 0.f, 0.f, 1.f); // red
212 mi::base::Handle<nv::index::IDistributed_compute_technique> mapping(
213 processing->get_sample_tool_set()->create_color_encoded_elevation_technique(height_range, color0, color1));
214 check_success(mapping.is_valid_interface());
215
216 // Add the mapping to the scene before the heightfield
217 mi::neuraylib::Tag mapping_tag = transaction->store_for_reference_counting(mapping.get());
218 static_group_node->append(mapping_tag, transaction);
219 }
220 }
221
222
224 nv::index::app::IApplication_layer* app_layer,
225 nv::index::IScene* scene,
226 mi::math::Bbox<mi::Float32, 3>& heightfield_bbox,
227 mi::neuraylib::IDice_transaction* transaction) const
228 {
229 // Details for creating a synthetic heightfield.
230 const mi::math::Vector<mi::Uint32, 2> heightfield_size(2000, 2000);
231 std::map<std::string, std::string> heightfield_opt;
232 heightfield_opt["type"] = "heightfield";
233 heightfield_opt["importer"] = "nv::index::plugin::legacy_importer.Synthetic_heightfield_generator";
234 heightfield_opt["synthetic_type"] = "i";
235 heightfield_opt["size"] = "2000 2000";
236 heightfield_opt["range"] = "0.1 1000";
237 nv::index::IDistributed_data_import_callback* importer_callback =
238 get_importer_from_application_layer(
239 app_layer,
240 "nv::index::plugin::legacy_importer.Synthetic_heightfield_generator",
241 heightfield_opt);
242
243 // Create heightfield scene element and add it to the scene
244 const mi::Float32 rotate_k = 0.0f;
245 const mi::math::Vector<mi::Float32, 3> translate(0.0f, 0.0f, 0.0f);
246 const mi::math::Vector<mi::Float32, 3> scale(0.5f, 0.5f, 0.5f);
247 const mi::math::Vector<mi::Float32, 2> elevation_range(0.0f, 128.0f);
248
249 mi::base::Handle<nv::index::IRegular_heightfield> heightfield_scene_element(
250 scene->create_regular_heightfield(
251 scale, rotate_k, translate,
252 heightfield_size,
253 elevation_range,
254 importer_callback,
255 transaction));
256 check_success(heightfield_scene_element.is_valid_interface());
257
258 heightfield_bbox = heightfield_scene_element->get_IJK_bounding_box();
259
260 // Set the name of the heightfield scene element
261 const std::string heightfield_name = "synthetic lod heightfield";
262 heightfield_scene_element->set_name(heightfield_name.c_str());
263
264 // ... and store the heightfield scene element in the distributed database ...
265 mi::neuraylib::Tag heightfield_tag =
266 transaction->store_for_reference_counting(heightfield_scene_element.get(), mi::neuraylib::NULL_TAG,
267 "lod_heightfield_scene_element");
268 return heightfield_tag;
269 }
270
271
272 //mi::neuraylib::Tag create_imported_heightfield(
273 // nv::index::IScene* scene,
274 // mi::math::Bbox<mi::Float32, 3>& heightfield_bbox,
275 // mi::neuraylib::IDice_transaction* transaction) const
276 //{
277 // // WIP
278 //}
279
280
281
283 nv::index::app::IApplication_layer* app_layer,
284 bool enable_LOD,
285 Scene_info& scene_info,
286 const mi::math::Bbox< mi::Float32, 3>& roi_bbox,
287 const mi::neuraylib::Tag& session_tag,
288 std::map<std::string, std::string>& opt_map,
289 mi::neuraylib::IDice_transaction* transaction) const
290 {
291 // Access the session instance from the database.
292 mi::base::Handle<const nv::index::ISession> session(
293 transaction->access<const nv::index::ISession>(session_tag));
294 check_success(session.is_valid_interface());
295
296 // Access (edit mode) the scene instance from the database.
297 mi::base::Handle<nv::index::IScene> scene(
298 transaction->edit<nv::index::IScene>(session->get_scene()));
299 check_success(scene.is_valid_interface());
300
301 // Create static group node for large data
302 mi::base::Handle<nv::index::IStatic_scene_group> static_group_node(
303 scene->create_scene_group<nv::index::IStatic_scene_group>());
304 check_success(static_group_node.is_valid_interface());
305
306
307
308 mi::neuraylib::Tag heightfield_tag;
309 mi::math::Bbox<mi::Float32, 3> heightfield_bbox;
310 {
311 heightfield_tag = create_synthetic_heightfield(app_layer, scene.get(), heightfield_bbox, transaction);
312 check_success(heightfield_tag.is_valid());
313 }
314
315
316 if (enable_LOD)
317 {
318 // Heightfield rendering properties
319 mi::base::Handle<nv::index::IRegular_heightfield_rendering_properties> hf_prop(
320 scene->create_attribute<nv::index::IRegular_heightfield_rendering_properties>());
321 check_success(hf_prop.is_valid_interface());
322
323 hf_prop->set_lod_rendering_enabled(true); // if false all black!
324 hf_prop->set_lod_pixel_threshold(2.f);
325 hf_prop->set_enabled(true);
326
327 mi::neuraylib::Tag hf_prop_tag = transaction->store_for_reference_counting(hf_prop.get());
328 check_success(hf_prop_tag.is_valid());
329
330 static_group_node->append(hf_prop_tag, transaction);
331 }
332
333
334
335 // Add a light and a material to the static group node
336 add_light_and_material(opt_map["hfield.texture"], scene.get(), static_group_node.get(), transaction);
337
338 add_texture_mapping(app_layer, opt_map["hfield.texture"], heightfield_bbox, scene.get(), static_group_node.get(), transaction);
339
340
341 // Append the surface sample program
342 const int user_prg = nv::index::app::get_sint32(opt_map["user_program_mode"]);
343 if (user_prg) {
344 mi::base::Handle<nv::index::ISurface_sample_program> surface_sample_program(
345 scene->create_attribute<nv::index::ISurface_sample_program>());
346 check_success(surface_sample_program.is_valid_interface());
347
348 std::string program_src = scene_info.rtc_program_source;
349 if (program_src.empty()) {
350 program_src = program_begin;
351 program_src.append(color_program);
352 if (user_prg > 1) {
353 program_src.append(inquire_program);
354 }
355 program_src.append(program_end);
356 scene_info.rtc_program_source = program_src;
357 }
358 surface_sample_program->set_program_source(program_src.c_str());
359
360 const mi::neuraylib::Tag surface_program_tag =
361 transaction->store_for_reference_counting(surface_sample_program.get());
362 check_success(surface_program_tag.is_valid());
363 static_group_node->append(surface_program_tag, transaction);
364 }
365
366
367 // Append the heightfield to the scene group
368 static_group_node->append(heightfield_tag, transaction);
369
370
371 mi::neuraylib::Tag static_group_tag = transaction->store_for_reference_counting(static_group_node.get());
372 check_success(static_group_tag.is_valid());
373
374 // append the static scene group to the hierachical scene description.
375 scene->append(static_group_tag, transaction);
376
377
378 return true;
379 }
380
381
383 const mi::neuraylib::Tag& camera_tag,
384 mi::neuraylib::IDice_transaction* transaction) const
385 {
386 check_success(camera_tag.is_valid());
387 check_success(transaction != 0);
388
389 mi::base::Handle<nv::index::IPerspective_camera> cam(
390 transaction->edit<nv::index::IPerspective_camera>(camera_tag));
391 check_success(cam.is_valid_interface());
392
393 // Set the camera parameters to see the whole scene
394 const mi::math::Vector<mi::Float32, 3> from(2000, 2000, -30);
395 const mi::math::Vector<mi::Float32, 3> to(0.f, 0.f, -30.f);
396 const mi::math::Vector<mi::Float32, 3> up(0.f, 0.f, 1.0f);
397 mi::math::Vector<mi::Float32, 3> viewdir = to - from;
398 viewdir.normalize();
399
400 cam->set(from, viewdir, up);
401 cam->set_aperture(0.033f);
402 cam->set_aspect(1.0f);
403 cam->set_focal(0.03f);
404 cam->set_clip_min(2.0f);
405 cam->set_clip_max(1000.0f);
406 }
407
408};
409
410}//heightfield_common
411
412
414
415
417{
418public:
419 const char* name() const { return "LOD Heightfield"; }
420
422 nv::index::app::IApplication_layer* app_layer,
423 Scene_info& scene_info,
424 const mi::math::Bbox< mi::Float32, 3>& roi_bbox,
425 const mi::neuraylib::Tag& session_tag,
426 std::map<std::string, std::string>& opt_map,
427 mi::neuraylib::IDice_transaction* transaction) const
428 {
430 app_layer,
431 true /*enable_LOD*/,
432 scene_info, roi_bbox, session_tag, opt_map, transaction);
433 }
434};
435
436}
437
438#endif
439
440
void setup_camera(const mi::neuraylib::Tag &camera_tag, mi::neuraylib::IDice_transaction *transaction) const
void register_classes(nv::index::IIndex *index_interface) const
void add_light_and_material(const std::string &texture_type, nv::index::IScene *scene, nv::index::IStatic_scene_group *static_group_node, mi::neuraylib::IDice_transaction *transaction) const
bool create_heightfield_scene(nv::index::app::IApplication_layer *app_layer, bool enable_LOD, Scene_info &scene_info, const mi::math::Bbox< mi::Float32, 3 > &roi_bbox, const mi::neuraylib::Tag &session_tag, std::map< std::string, std::string > &opt_map, mi::neuraylib::IDice_transaction *transaction) const
void usage_info(std::ostream &os, const char *indent, std::map< std::string, std::string > &opt_map) const
void add_texture_mapping(nv::index::app::IApplication_layer *app_layer, const std::string &texture_type, const mi::math::Bbox< mi::Float32, 3 > &heightfield_bbox, nv::index::IScene *scene, nv::index::IStatic_scene_group *static_group_node, mi::neuraylib::IDice_transaction *transaction) const
mi::neuraylib::Tag create_synthetic_heightfield(nv::index::app::IApplication_layer *app_layer, nv::index::IScene *scene, mi::math::Bbox< mi::Float32, 3 > &heightfield_bbox, mi::neuraylib::IDice_transaction *transaction) const
void add_arguments(std::map< std::string, std::string > &opt_map) const
bool create_scene(nv::index::app::IApplication_layer *app_layer, Scene_info &scene_info, const mi::math::Bbox< mi::Float32, 3 > &roi_bbox, const mi::neuraylib::Tag &session_tag, std::map< std::string, std::string > &opt_map, mi::neuraylib::IDice_transaction *transaction) const
static const char * inquire_program
static const char * program_end
static const char * color_program
static const char * program_begin
Scene setup interface for ray sampling example.
#define check_success(expr)