Material and Texture API limitations

I’m trying to deal with textures and I’m finding it’s a bit difficult.

You can’t list textures that are being used by a material, you need to know beforehand what slots should be occupied.

  • There’s GetTexture, SetTexture, but the internal dictionary isn’t exposed at all. I’d like to fetch all textures on a given material and change their paths. In another scenario I’m trying to embed them all. And another scenario where i want to convert embedded textures into a relative file path (un-embed them). In that case I’ve found I have to create a whole new material and texture instance to replace the existing ones, as they kept track of the old texture path and wouldnt work with my new relative path.

  • Will SetTexture override the existing texture occupying that slot?

  • What is the best approach for getting SlotNames that are supported? Are some slots supported in the more common formats? I mostly use fbx and gltf. I’ve had to look into fbx ascii output and see what slotnames are being used.

@bortos

We need to check relevant details in order to share our feedback against each scenario. Meanwhile, could you please also share sample file(s) for our reference which you want to process using the API? Also, please share in which platform e.g. .NET/Java you are working?

Hi, I use the .NET API

There’s no specific file I want to process, its mainly an API limitation with textures.

If I load a model and want to modify textures of one of my meshes I would expect to do the following:

var targetNode = outputScene.RootNode.ChildNodes.First()
if(targetNode.Material.TextureMappings.TryGetValue("DiffuseColor", out var texture))
{
  // save the texture to disk      
  var filePath = "C:\Test.png"
  File.WriteAllBytes(filePath, texture.Content);

  // remove embedded data
  texture.Content = null;

  // Set content path
  replacementTexture.FileName = filePath;
}


// Save scene

The code above would open a scene, and store any embedded diffuse texture to disk. The output file should now have an absolute texture reference on the material. File size should go down.

Unfortunately the above is not really possible. The only approach I can find is to do the following:

            var textures = outputScene.Library.OfType<Texture>().ToList();

Even with that, I cant get the material that references it. In my case I can make the assumption, however the API should let me see what textures are used by what materials.

An additional problem I found with FBX files is the early code that changed embedded content to a file reference was not being saved properly. However, I will leave that for another thread.

This thread is primarily the API doesn’t provide a way to discover textures on materials.

@bortos

Thanks for elaborating on the issue further.

We have logged an investigation ticket as THREEDNET-813 in our issue tracking system for it. We will further look into its details and keep you posted with the status of its rectification. Please be patient and spare us some time.

We are sorry for the inconvenience.

@bortos

Yes, passing null will remove the specified slot, if you want to use FBX compatible layered texture to represent multiple textures, we can expose the internal layered texture in the following version.

The available slot names are defined as constant in Material.Map****, and PbrMaterial.Map***, PbrSpecularMaterial.Map***

Since 21.2v, all texture slots can be accessed through IEnumerable that will be implemented in Material, then you can use the following code to enumerate all texture slots:

foreach(var texSlot in mat)
{
 Console.WriteLine(texSlot.SlotName);
 Console.WriteLine(texSlot.Texture);
}

Material is a lightweight class in Aspose.3D, it does not use Dictionary internally. A hotfix will be released soon for this.

@bortos

Please try using Aspose.3D for .NET 21.1.1 hotfix which resolves the above issue.