I am writing an exporter and importer for a non-standard file format.
For exporting pbr materials, I am able to get texture paths and other values this way (shortened example!):
{
matInfo.isPhysicallyBased = true;
//cycle throught textures and get each type.
const ON_PhysicallyBasedMaterial pbrMat = rhinoMat;
//get other attributes similar to Rh6 materials
int totalTextures = pbrMat.Material().m_textures.Count();
for (int x = 0; x < totalTextures; x++)
{
if (pbrMat.Material().m_textures[x].m_type == ON_Texture::TYPE::opacity_texture) //BITMAP_TEXTURE DEPRECATED
{
if (pbrMat.Material().m_textures[x].IsValid()) // Sometimes support files are missing
{
try
{
const ON_wString textPathW = pbrMat.Material().m_textures[x].m_image_file_reference.FullPath();
//save this value for use with my custom export
}
catch (...)
{
}
}
}
}
ON_4fColor emissionColorToSave(pbrMat.Emission());
}
However, I want to recreate a fully defined pbr material, not a “custom” material.
I have tried this:
bool isPPBR = false;
//Set up both types
ON_Material rMat;
ON_Color col(255, 0, 0); // Initial color.
rMat.SetDiffuse(col);
rMat.SetName(L"myMaterialName");
ON_PhysicallyBasedMaterial pbrMat = rMat;
if (myImporterFinds_PBR_tag)
{
isPBR = true;
}
//Loop to get each line from my custom file format, some examples of data collected:
while (getline(myMaterialFile, line))
{
if (line.find("opacity_texture: ") != std::string::npos)
{
// call my helper function to get the path value
pbrMat.AddTexture(getPathFromline(line), ON_Texture::TYPE::pbr_opacity_ior_texture);
}
else if (line.find("emission_color: ") != std::string::npos)
{
if (isPPBR)
{
ON_4fColor emColor;
// call my helper function to get the color value
getColor4(line, &emColor);
pbrMat.SetEmission(emColor);
}
else
{
ON_Color emColor;
// call my helper function to get the color value
getColor(line, &emColor);
rMat.SetEmission(emColor);
}
}
else
{
// more code to handle importing data about the material
}
} //end of while loop
//after collecting all the material data, create the material
if (isPPBR)
{
// What do I do here??????
}
else
{
const int matIndex = RhinoApp().ActiveDoc()->m_material_table.AddMaterial(rMat);
}
Firstly, you need to be using the modern “RDK” methods to work with these richer material definitions. There are plenty of samples - but this should be a good start:
The function CRhRdkMaterial::FromOnMaterial will create a Physically Based material from an ON_Material that is actually a PBR.
I pulled the rhino-developer-samples yesterday. Building samples.sln in VS2019 resulted in a lot of errors. Building just SampleRdkAddRdkMaterials had two errors:
|Error|C2664|'CRhRdkSimulatedTexture::CRhRdkSimulatedTexture(const CRhRdkSimulatedTexture &)': cannot convert argument 1 from 'CRhinoDoc *' to 'const CRhRdkSimulatedTexture &'|SampleRdkAddRdkMaterials|E:\GitE\rhino-developer-samples\cpp\SampleRdkAddRdkMaterials\SampleRdkAddRdkMaterialsCommand.cpp|34||
|Error|C2039|'SetDiffuse': is not a member of 'CRhRdkMaterial'|SampleRdkAddRdkMaterials|E:\GitE\rhino-developer-samples\cpp\SampleRdkAddRdkMaterials\SampleRdkAddRdkMaterialsCommand.cpp|31||
I modified those two lines of code, and set line 35 to point to a .jpg on my system:
// Optionally set the diffuse color again.
//pMaterial->SetDiffuse(RGB(0, 255, 0));
// Add a bitmap texture to the bitmap slot of the Basic Material.
CRhRdkSimulatedTexture tex; // (pDoc);
It will now build, but will crash when run, until I commented out the “dib” section, lines 52 to 72.
With those changes, it will run and create a material, but the material type is “Custom”
All, Updating the SDK helped some. Everything compiles with only the need to comment out
//pMaterial->SetDiffuse(RGB(0, 255, 0));
when run, it still crashes unless I remove the dib texture code, lines 52 to 72.
And it is still creating a “Custom” layer, not a “Physically Based” layer.
I need to assign multiple textures, and although my code does so without throwing any errors, In Rhino the material appears as a custom type with only one texture.
And yes - you will need to use CRhRdkMaterial::FromOnMaterial instead of RhRdkNewBitmapTexture if you want the ON_Material in PBR mode to create a PBR material. You’ll see it in the new sample code.
Thank you, I downloaded the sample changes, and this is much closer. It does create a Physically Based material with the two textures shown in the sample. However, when I try to add a texture for metallic, it does not appear (shown here between the original lines of code):
// Add a bitmap texture to the bitmap slot of the Basic Material.
CRhRdkSimulatedTexture tex(pDoc);
tex.SetFilename(L"C:\\myLocalBmpBase.bmp", pDoc, false);
auto* pBitmap = ::RhRdkNewBitmapTexture(tex, pDoc);
if (nullptr != pBitmap)
{
pPBR->SetChild(pBitmap, CS_MAT_PBR_BASE_COLOR);
pPBR->SetChildSlotOn(CS_MAT_PBR_BASE_COLOR, true);
}
//Attempt to add a metallic texture here
CRhRdkSimulatedTexture tex2(pDoc);
tex2.SetFilename(L"C:\\myLocalBmpMet.bmp", pDoc, false);
auto* pBitmap2 = ::RhRdkNewBitmapTexture(tex, pDoc);
if (nullptr != pBitmap2)
{
pPBR->SetChild(pBitmap, CS_MAT_PBR_METALLIC);
pPBR->SetChildSlotOn(CS_MAT_PBR_METALLIC, true);
}
// Add a wood texture to the transparency slot of the Basic Material.
auto* pWood = ::RhRdkContentFactoriesEx().NewContentFromTypeEx(uuidWoodTextureType, pDoc);
if (nullptr != pWood)
{
pPBR->SetChild(pWood, CS_MAT_PBR_ROUGHNESS);
pPBR->SetChildSlotOn(CS_MAT_PBR_ROUGHNESS, true);
}
Found another issue. Even though the SampleRdkAddRdkMaterialsCommand.cpp code is trying to create a PBR with the name “Sample PBR”, as shown here:
//Now do the same for a PBR material.
// Create an ON_Material as a PBR.
ON_Material mat;
mat.SetName(L"Sample PBR");
mat.ToPhysicallyBased();
ASSERT(mat.IsPhysicallyBased());
auto pbr = mat.PhysicallyBased();
ON_4fColor col;
col.SetRGBA(1.f, 0.f, 0.f, 1.f);
pbr->SetBaseColor(col);
pPBR = CRhRdkMaterial::FromOnMaterial(mat, pDoc);
The material is being created with the name “Physically Based”, which can be seen in the last image included here. Should it inherit the name from the “mat” variable, or is there another way to set the name on the “pPBR” object?