Hi all. I’m trying to write a file with embedded textures but can’t find it in the rhino3dm docs. I’m looking for the same functionality as “save textures” checkbox when saving manually.
I create new File3dm(), then add some materials and geometry from another file, and then call file3dm.Write(). It creates a file but no textures.
I’m creating a File3dm instance in memory, then adding objects and materials manually. This file is loaded in Three.js using 3DMLoader.js. The material properties and colors show up, but the textures don’t.
3DMLoader uses doc.getEmbeddedFileAsBase64(filename) to retrieve the textures, but throws an error that the textures are not found.
Is there any way to embed files to the File3dm object in C#, that will be able to be retrieved using the getEmbeddedFileAsBase64 function?
I’m a bit out of my depth here when you mention .js and 3DMLoader which I am not familiar with. I also don’t know about doc.getEmbeddedFileAsBase64 and I can’t find that function in our code base. In light of that, I may be confused so what I say next might not be helpful, but here goes.
I have recently added a new EmbeddedFiles feature to Rhino 8’s File3dm. These embedded files are the same as the ones saved by the “save textures” checkbox when saving manually. You can add and access embedded files like this:
bool TestEmbeddedFiles()
{
// Load a model from a 3dm file.
var file3dm = Rhino.FileIO.File3dm.Read("MyInputFile.3dm");
if (file3dm == null)
return false;
// Add a new embedded file from a file on disk.
if (!file3dm.EmbeddedFiles.Add("MyPicture.jpg"))
return false;
// Iterate over the embedded files in the model.
foreach (var ef in file3dm.EmbeddedFiles)
{
var filename = ef.Filename;
...
}
if (!file3dm.Write("MyOutputFile.3dm", 0))
return false;
return true;
}
Note that the file names must be the fully-qualified paths to the files.
This new feature is still under internal review and may change before Rhino 8 is released, but this is the basic idea of how it will work.
Thanks, I understand then that EmbeddedFiles will only be available in Rhino 8, and it’s also not possible to embed textures in any other way using Rhino 7 when creating a File3dm object in memory.
I’m trying to avoid having to save it to disk as a temp file and read it back to memory, which it looks like it’s the only way to get the textures embedded in Rhino 7.
It seems to read from m_userdata_table, which is related to (or the same as) File3dmPlugInDataTable, which does exit in Rhino 7’s File3dm class but you can only read from it I think.
The C# stuff is not my area of expertise, but I’m pretty sure Rhino 7 does not have a way of adding or otherwise manipulating the embedded files in C#. I could be wrong, so I’ll ask @andy to chime in if he knows better.
FYI: Unfortunately there is some confusion with the concept of ‘embedded files’ because of a legacy system to do with Rhino’s bitmap table which sometimes also uses the term ‘embedded’.
The embedded files I’m discussing here are the ones that are referenced by Render Textures and saved when you check the ‘Save textures’ check box in the Save As dialog. Anything to do with ‘bitmap table’ or File3dmPlugInDataTable is not the same and will not do what you need.
That’s strange, what I can gather from the GitHub repo is that both GetEmbeddedFileAsBase64 (used to load textures), and File3dmPlugInDataTable read from the same native array m_model->m_userdata_table.
I think @fraguada has worked on the 3dm loader and might know something about this as well.
I’ve checked with Andy and I stand corrected! I didn’t realize that File3dmPlugInDataTable provided access to that data! Like I said, C# is not my area of expertise. I’m told that those functions are there to provide access to stuff in the 3dm file that was otherwise unavailable. It’s not “full featured” and it’s being replaced in Rhino 8. I also understand that this stuff is read-only.
However, to be on the safe side, let’s ask Luis @fraguada and also @nathan might know something about this.
@visose in rhino3dm dotnet you have EmbeddedFileTable.Add(string filename) that adds a file to the table. If you create a texture with the same filename, then doc.getEmbeddedFileAsBase64(filename) should work to retrieve the file.