Add materials from .mtl file not working

I am reading a .obj and .mtl file and trying to add materials to a mesh which I import using some C++ code. The .mtl file has entries like:

newmtl material_2
Ka 0.0000 0.0000 0.0000
Kd 1.0000 0.0000 0.0000
Ks 1.0000 1.0000 1.0000
Tf 0.0000 0.0000 0.0000
d 1.0000
Ns 127.5

In my C++ code for the material definition part I tried:

// Create attributes for mesh.
ON_3dmObjectAttributes attribs;
// Assign default values.
pDoc->GetDefaultObjectAttributes(attribs);
// Create new material.
ON_Material mat;
// Converted material_2 string to wchar_t* namew to name material.
mat.SetName(namew);
// Parsed Ka 3 floats, converted to 0-255 range stored in rgb[3] and then set ambient color.
mat.SetAmbient(ON_Color(rgb[0], rgb[1], rgb[2]));
// Parsed Kd 3 floats, converted to 0-255 range stored in rgb[3] list and then set diffuse color.
mat.SetDiffuse(ON_Color(rgb[0], rgb[1], rgb[2]));
// Parsed Ks 3 floats, converted to 0-255 range stored in rgb[3] list and then set specular color.
mat.SetSpecular(ON_Color(rgb[0], rgb[1], rgb[2]));
// Get material index for new material.
const int32_t matIndex = pDoc->m_material_table.AddMaterial(mat);
// Add Material index.
attribs.m_material_index = matIndex;
// Set color source to be from material. THIS GOT IT WORKING.
attribs.SetColorSource(ON::color_from_material);
// Set material source to be from object.
attribs.SetMaterialSource(ON::material_from_object);
// Add mesh with attribs to Document.
CRhinoMeshObject* meshObject = new CRhinoMeshObject(attribs);
pDoc->AddObject(meshObject

I did not know what to do with Ns.

When I look at the mesh I see:


which shows that the name and color showed up fine in material_2 definition.
But when I look at the mesh in Rendered view all I see is black:

instead of red that was in the original mesh which was exported to .obj file:

Here are material_2 details for the original mesh:

It has Gloss set to 50% and Reflection set to 5% which is different but not enough to control whether the diffuse color is shown.

Curiously, for the original mesh, the Textures Bump setting is 100% whereas in my imported version it appears as 30%. How is this even possible?

Obviously something is missing.

I need help with handling Ns from the .mtl file. Will adding this fix the problem?

Here is the .3dm file of the imported mesh:
vertex_colors materials not showing up.3dm (4.1 MB)
Here is the .mtl file (copied flat as .mtl extension not allowed):

# Rhino
newmtl material_2
Ka 0.0000 0.0000 0.0000
Kd 1.0000 0.0000 0.0000
Ks 1.0000 1.0000 1.0000
Tf 0.0000 0.0000 0.0000
d 1.0000
Ns 127.5000
newmtl Default
Ka 0.0000 0.0000 0.0000
Kd 0.9804 0.9804 0.9804
Ks 1.0000 1.0000 1.0000
Tf 0.0000 0.0000 0.0000
d 1.0000
Ns 0.0000
newmtl material_1
Ka 0.0000 0.0000 0.0000
Kd 0.5451 0.3529 0.0000
Ks 1.0000 1.0000 1.0000
Tf 0.0000 0.0000 0.0000
d 1.0000
Ns 38.2500
newmtl material_3
Ka 0.0000 0.0000 0.0000
Kd 1.0000 0.4980 0.0000
Ks 1.0000 1.0000 1.0000
Tf 0.0000 0.0000 0.0000
d 1.0000
Ns 0.0000

Here is the .obj file:
vertex_colors no texture.obj (5.6 MB)

Regards,
Terry.

Maybe this?

static void SetMaterialShine(ON_Material& material, double Ns)
{
  // The obj/mtl book suggest this value is between 0 and 1000.
  // Assume values < 100 means between 0 and 100. 
  if (Ns > 100.0)
    material.m_shine = Ns / 1000 * ON_Material::MaxShine;
  else
    material.m_shine = Ns / 100 * ON_Material::MaxShine;
}

– Dale

1 Like

Dale,

I added 1 line:

attribs.SetColorSource(ON::color_from_material);

and this got the material colors to display in Rendered View.
:

I tried your Ns suggestion but it did not create any visual difference.

Now there are only 2 outstanding issues:
(1) The color/sheen of the brown/bronze ring does not match the original:

The custom material data for the ring seem to be the same:

Is Rhino not generating the right .mtl file to go with the original mesh?

(2) The one difference you can see in the above material settings is the Bu/No. value is 100% for the original and 30% for the copy. Does this matter? How can it be fixed? When I click to add texture I just get lost.

Original .3dm file:
vertex-colors.3dm (4.1 MB)
Original .obj file that was exported:
vertex-colors.obj (8.4 MB)
.mtl file that goes with .obj file (.mtl extension changed to .txt to enable upload):
vertex-colors.txt (585 Bytes)
Imported .3dm file:
Vertex_colors_imported.3dm (4.2 MB)

Regards,
Terry.

The difference is in the settings in the rendering panel:

Original:

Imported:

Especially the gamma 2.2 and use linear workflow - make them the same and colors will match.

The one in imported is what the defaults are for new rhino files, the original has non-default settings.

Note also that in imported file background is set to solid white whereas original has 360° env as background. Additionally imported has same env for custom reflection environment.

2 Likes

Excellent work. :weight_lifting_man:

That sure does the trick: :grinning:

I know next to nothing about materials as most of the meshes I have dealt with have texture maps that use large .jpg files. Those work great for me when I import and analyze them.

Now I can at least get some of the basics to work with custom materials thanks to your’s and Dale’s help. Plus lots of reading of the Rhino C++ API files.

The Bump/Normal setting is still stuck at 30% for all 3 materials even after matching the Render settings. Do you know what that is about?

Regards,
Terry.

We’ll have to poke @johnc for how to do this in C++ (fiddle with bump/normal setting).

Dale,

I tried your suggestion for Ns again now that I have the Rendering environment setup to match the original. Changing the shine does change the value shown for the Gloss finish under Custom Settings and the appearance of the mesh.

There is a problem however. The original mesh shows a Gloss finish of 15% and 50% for Materials 1 & 2 respectively. However Rhino creates an .mtl file with values of 38.25 & 127.5 for Materal 1 & 2. Using your formulas these create Gloss finish values of 38.25% and 13%.

If instead I just use:

material.m_shine = Ns;

Then Gloss finish comes out to be 15% and 50% as desired. There seems to be no need for an Ns conversion formula to set: material.m_shine.

From this I conclude that Ns has a range from 0 to 255. Thus an Ns of 127.5 is 50% of the MaxShine value of 255 while 38.25 is 15% of 255. Seeing your formula reminded me of the connection to MaxShine.

Now I have closure on how to use all these values:

# Rhino
newmtl material_2
Ka 0.0000 0.0000 0.0000
Kd 1.0000 0.0000 0.0000
Ks 1.0000 1.0000 1.0000
Tf 0.0000 0.0000 0.0000
d 1.0000
Ns 127.5000
newmtl Default
Ka 0.0000 0.0000 0.0000
Kd 0.9804 0.9804 0.9804
Ks 1.0000 1.0000 1.0000
Tf 0.0000 0.0000 0.0000
d 1.0000
Ns 0.0000
newmtl material_1
Ka 0.0000 0.0000 0.0000
Kd 0.5451 0.3529 0.0000
Ks 1.0000 1.0000 1.0000
Tf 0.0000 0.0000 0.0000
d 1.0000
Ns 38.2500
newmtl material_3
Ka 0.0000 0.0000 0.0000
Kd 1.0000 0.4980 0.0000
Ks 1.0000 1.0000 1.0000
Tf 0.0000 0.0000 0.0000
d 1.0000
Ns 0.0000

from the .mtl file to set the values in the Custom Settings section of the Properties Material Panel for each material. Plus it provides values for the Ambient color, Specular color and Emission color.

Now if I can just chase down how the Bump/Normal setting of 30% in the Textures section comes about when the original mesh shows 100%.

Regards,
Terry.

Hi @Terry_Chappell,

Sorry for the delay on this. The problem with setting the Bump (30%) property is that this is a ‘modern’ setting but the code you’re using to create the material is kind of ‘old-school’ and doesn’t support the latest material properties.

I am working on a sample to demonstrate a better way to write the code so you can get at all the ‘new-school’ settings. I just need to get help from someone who understands meshes and I will post the sample here as soon as I can.

John

John,

Nice to hear from you about the Bump issue. I look forward to expanding my understanding of material specifications for Rhino meshes.

Regards,
Terry.

Hi @Terry_Chappell,

Sorry again for the delay. I finally got this figured out and I’ll post some example code. I’m using a sphere mesh as an example because I don’t have all your code for importing the real mesh. The biggest difference in this new code compared to the old-school method is the need to use ‘RDK materials’ (AKA Render Materials) instead of just using the more simple ON_Material by itself. The example ends by showing how to change the Bump slot from 30% to 100%. Note that this won’t do anything unless a texture is also assigned to the bump slot. If you need help doing that or anything else, please feel free to ask.

Regards,

John

bool AddNewMaterial(CRhinoDoc* pDoc, const wchar_t* namew, const int* rgb)
{
	// Create new material.
	ON_Material mat;

	// Converted material_2 string to wchar_t* namew to name material.
	mat.SetName(namew);

	// Parsed Ka 3 floats, converted to 0-255 range stored in rgb[3] and then set ambient color.
	mat.SetAmbient(ON_Color(rgb[0], rgb[1], rgb[2]));

	// Parsed Kd 3 floats, converted to 0-255 range stored in rgb[3] list and then set diffuse color.
	mat.SetDiffuse(ON_Color(rgb[0], rgb[1], rgb[2]));

	// Parsed Ks 3 floats, converted to 0-255 range stored in rgb[3] list and then set specular color.
	mat.SetSpecular(ON_Color(rgb[0], rgb[1], rgb[2]));

	// Create a Custom Material from 'mat'.
	auto* material = CRhRdkMaterial::FromOnMaterial(mat, pDoc);
	if (nullptr == material)
		return false;

	// Attach the material to the document.
	auto& contents = pDoc->Contents().BeginChange(RhRdkChangeContext::Program);
	contents.Attach(*material);
	contents.EndChange();

	// Create attributes for mesh.
	ON_3dmObjectAttributes attribs;

	// Assign default values.
	pDoc->GetDefaultObjectAttributes(attribs);

	// Set color source to be from material. This is used when drawing the mesh in wireframe.
	attribs.SetColorSource(ON::color_from_material);

	// Add mesh with attribs to the document. I use a sphere mesh here as I don't have the real
	// code that creates the mesh in the user's plug-in.
	CRhinoMeshObject* meshObject = new CRhinoMeshObject(attribs);
	ON_Mesh* mesh = ::RhinoMeshSphere(ON_Sphere(ON_3dPoint::Origin, 10.0), 20, 20);
	meshObject->SetMesh(mesh);
	pDoc->AddObject(meshObject);

	// Assign the material to the mesh. This is used when rendering the material in
	// Rendered / Shaded etc., or Raytraced views or when using the Render command.
	CRhRdkObjectDataAccess da(meshObject);
	da.SetMaterialInstanceId(material->InstanceId());

	// Change the bump amount from 30% to 100%.
	auto& m = material->BeginChange(RhRdkChangeContext::Program);
	m.SetChildSlotAmount(CS_MAT_BUMP_TEXTURE, 100.0);
	m.EndChange();

	return true;
}

John,

This looks quite interesting. I will try it out soon to see it it lets me control the bump setting on the mesh I am using to test my import program.

Is this new method documented somewhere?

Regards,
Terry.

Hi @Terry_Chappell,

Sorry again for the delay; I was on summer vacation.

The new method of creating materials is documented in some of our samples. In particular, SampleRdkAddRdkMaterials, although it’s not as detailed as the above sample which was tailored to what you need. You can check out this sample code here:

Regards,

John

Thanks for the addition example. I will be getting back to this issue after I finish my current work on vertex normals.

Regards,
Terry.