Bug in OptiXMesh - setOptiXMaterial() doesn't set materials in the right order

My OptiXMesh loader loads an .obj-file with 20 different materials, which are defined in a .mtl-file.
To use my own closest/anyhit program, I use setOptiXMaterial() with some material paprameters defined in a material database.

for(int i=0; i<mesh_loader.getMaterialCount(); i++)
 {
    std::string mat_name = mesh_loader.getMeshMaterialParams(i).name;
    mesh_loader.setOptiXMaterial(i, m_materialDB.getMaterial(mat_name) );
 }

Although the names of the mesh materials are in the right order, I don’t get the materials set properly.
Is this problem related to the known Bug in MeshBase.cpp (line 578)?

m_material_params = staging_materials; // BUG: Doesn't respect name to index mapping

Unfortunately there are several problems with the Mesh and MeshLoader classes in the 3.9 SDK. To solve this and to reduce overall sutil complexity we greatly simplified and rewrote the sutil library (including mesh related codes) in 4.0. I would take a look at the 4.0 mesh loader and see if that suits your use case. It is much simpler so extending it to fit your needs should be straightforward.

Thank you. I’ve now looked into the code of OptiX 4.0. Unfortunately I have to change certain parts of my program now with the new version, also concerning my display. But I think it will be worth it, since the new mesh loader is really more clear.

Am I right that there is no possibilty now with the new OptixMesh loader to get the name of the materials from the .mtl file?

EDIT: I found a suitable position for injecting my material database into the new OptixMesh loader. Now with that modied version I should be able to set my material parameters again with my material database. I will show some code tomorrow, when I finally tested it.

I am glad things are working for you now. Let us know if you run into further problems.

Unfortunately I ran into another problem. When I try to built my c-module, which runs my optix code from a static library, it can’t find sutil functions. I always get the error:

/home/user/cuda-workspace/c-Modul/lib/libmyoptix.a(foo.o): In function MyOptiXClass::createContext()': /home/user/cuda-workspace/Optix-Project/Debug/../src/optix.cpp:91: undefined reference to sutil::createOutputBuffer(optix::Handleoptix::ContextObj, RTformat, unsigned int, unsigned int, bool)’

This error message includes all functions related to sutil. I already tried to use namespace sutil explicit but this doesn’t help. I checked the linker to the libraries and the sutil library can be found.
What can I do to get the sutil functions found?
Is it right, that my c-code can actually know what c++ code is missing?

EDIT: I now solved this problem with linking to sutil_sdk instead of sutil. But my program now gets always terminated a the point context->setRayTypeCount() with an segmentation fault.

This is how my c-function looks like, for creating the optix scene:

void* createScene( double* inputArray, double* outputArray, int argc, char** argv ){
	OptixScene* scene = new OptixScene();
	scene->routeInput(inputArray);
	scene->routeOutput(outputArray);

	scene->createContext();   // in this function it gets terminated!
	scene->loadMeshes();
	scene->setupCamera();
	scene->setupLights();
	scene->validateContext();
	std::thread display_thread(&OptixScene::displayScene, scene, argc, argv);
	display_thread.detach();

	return (void *)sensor;
}

createContext():

void OptixScene::createContext()
{
	// Set up context
	my_context -> create();
	my_context -> setRayTypeCount( 2 );  // terminates here!
	my_context -> setEntryPointCount( 1 );
	my_context -> setStackSize( 4096 );

	my_context[ "radiance_ray_type" ]  ->setUint ( 0u );
	my_context[ "shadow_ray_type" ]    ->setUint ( 1u );
	my_context[ "scene_epsilon" ]      ->setFloat( 1.e-4f );
	my_context[ "max_depth" ]          ->setInt  ( 2 );
	my_context[ "importance_cutoff" ]  ->setFloat( 0.1f );
	my_context[ "ambient_light_color" ]->setFloat( 1.0f, 1.0f, 1.0f );

	// Output buffer
	Buffer buffer = sutil::createOutputBuffer( my_context, RT_FORMAT_UNSIGNED_BYTE4, m_width, m_height, m_use_pbo );
	my_context["output_buffer"]->set( buffer );

	m_obj_id_buffer = my_context->createBuffer(RT_BUFFER_OUTPUT);
	m_obj_id_buffer -> setFormat(RT_FORMAT_USER);
	m_obj_id_buffer -> setElementSize(sizeof(float));
	m_obj_id_buffer -> setSize(m_width, m_height);
    my_context["Obj_ID_Buffer"] -> set(m_obj_id_buffer);

    // Ray generation program
    Program ray_gen_program = my_context->createProgramFromPTXFile( m_ptxPath + "scene.ptx", "pinhole_camera" );
    my_context->setRayGenerationProgram( 0, ray_gen_program );

    // Exception program
    Program exception_program = my_context->createProgramFromPTXFile( m_ptxPath + "scene.ptx", "exception" );
    my_context->setExceptionProgram( 0, exception_program );
    my_context[ "bad_color" ]->setFloat( 1.0f, 0.0f, 1.0f );

    // Miss program
    Program miss_program = my_context->createProgramFromPTXFile( m_ptxPath + "scene.ptx", "miss" );
    my_context->setMissProgram( 0, miss_program );
    my_context[ "bg_color" ]->setFloat( 0.0f, 0.0f, 0.0f );

#ifdef USE_DEBUG_EXCEPTIONS
    // Enable printing (for debugging only!)
    my_context->setPrintEnabled( true );
    my_context->setExceptionEnabled(RT_EXCEPTION_ALL, true);
    my_context->setPrintBufferSize( 2048 );
#endif
}

I’ve now solved my segmentation error after I removed some commented-out program blocks in my program. That was really weird…

I have noticed that the new mesh loader doesn’t set the material names. Is this on purpose or is it a missing feature?

Here are the codelines in Mesh.cpp (line 555) where the material parameters are handed over. The m_materials[i].name is missing, which I need for my material database. I will add it myself, but I think it would be a nice feature to read out material names from mtl files.

for( uint64_t i = 0; i < m_materials.size(); ++i )
  {
    MaterialParams mat_params;

    mat_params.Kd_map = m_materials[i].diffuse_texname.empty() ? "" :
                        directoryOfFilePath( m_filename ) + m_materials[i].diffuse_texname;

    mat_params.Kd[0]  = m_materials[i].diffuse[0];
    mat_params.Kd[1]  = m_materials[i].diffuse[1];
    mat_params.Kd[2]  = m_materials[i].diffuse[2];
    
    mat_params.Ks[0]  = m_materials[i].specular[0];
    mat_params.Ks[1]  = m_materials[i].specular[1];
    mat_params.Ks[2]  = m_materials[i].specular[2];

    mat_params.Ka[0]  = m_materials[i].ambient[0];
    mat_params.Ka[1]  = m_materials[i].ambient[1];
    mat_params.Ka[2]  = m_materials[i].ambient[2];

    mat_params.Kr[0]  = m_materials[i].specular[0];
    mat_params.Kr[1]  = m_materials[i].specular[1];
    mat_params.Kr[2]  = m_materials[i].specular[2];

    mat_params.exp    = m_materials[i].shininess;

    mesh.mat_params[i] = mat_params;
  }

Looks like we just missed copying the name field over. Thanks for the tip.