Need code snippet: import mesh/texture into content browser from C++ code.

I’m currently looking for a way to import mesh (either fbx file or generated one)/textures into content browser from C++ code, turning them into assets that can be used in level editor.

I’ll eventually figure that out myself, but if anyone has snippet to share or can point me at the right function, that’ll save me few hours of research.

So, can someone point me in the right direction? (Which functions can be used to do that/etc.)

I’m not saying it’s impossible, but as far as I know, this is not a standard feature that is documented (but I don’t claim to know the documentation inside out, so I might be mistaken). If you find out how to do it, please post it here :slight_smile:

I forgot to mention, but this is for editor plugin, not for runtime game code.
For runtime mesh generation there was sample “GeneratedMesh” (or something) class on the wiki.

There’s a lot of stuff that isn’t documented, which is why I asked for a snippet (someone probably tried to do that before and might have unused code lying around).

At the moment I’ve located function that seems to be doing what I need regarding textures:
UnrealEngine/Engine/Source/Editor/UnrealEd/Private/Fbx/FbxMaterialImport.cpp , Line 49 “UTexture* UnFbx::FFbxImporter::ImportTexture( FbxFileTexture* FbxTexture, bool bSetupAsNormalMap )”

And it looks like UFbxFactory should also be usable for mesh import.

Currently testing that.

Alright. I figured it out.

To create asset in content browser, you first create “UPackage *” with CreatePackage function,
then you create factory for object type you need and pass that package to the factory object creation routines, like FactoryCreateBinary, then mark package dirty and notify assetdatabase that package was created.

Here’s the catch.

Package name MUST start with “/Game/”. Generally it will be “/Game/someFolder/someSubfolder/someAssetName”.

If it DOESN’T start with “/Game/”, editor will crash within FactoryCreateBinary() and you’ll be getting unhelpful errors. “object not packaged” or “path does not map to any roots”.

Examples can be found within unreal code in the FbxMaterialimport.cpp, and also speed tree import functions.

Problem solved, unsubscribing.

Have you worked out how to make it generate the mipmaps for the texture you’re importing? I’m doing the same thing but I only ever get a single mipmap.

This is totally a supported feature. This example helped a lot: How to save asset in C++ runtime(play in game)? - C++ - Epic Developer Community Forums

No I haven’t looked into that (I don’t know for sure if I even have this issue), and most likely I won’t be looking into that any time soon.

I would advise to download engine source code and look how they do it there. That’s probably the best approach.

Also, the example you linked is quite different from the texture-asset-creating code I encountered in FbxImporter/SpeedTree importer.

So I can only recommend to download engine sources and check them out. Chances are if you use UTextureFactory, it might generate mipmaps for you. Even if it doesn’t, you should be able to pinpoint what is responsible for enabling mipmap generation.

Yeah, I did what you did and tried the code from the FBX importer. It’s failing to import at the moment but I’ll keep working through it.

I checked imported textures (imported from C++ code, I mean), and everything that I imported/created using UTextureFactory has full chain of generated mipmaps, as long as texture size is power of 2. The textures were loaded from png files, which do not have mipmaps stored in them.

You should probably look into UTextureFactory or scout the code for mip-map generation references.

I am just bad at reading nested code apparently :slight_smile: I’m lacking a valid header for my image data so I’ll have to figure one out, probably BMP. After that it should work.

That’s not a good idea.

Unreal engine has loading functions for several image formats. You need to reuse/hijack those instead of writing your own. That’s because reusing existing code reduces number of possible bugs. (If you have two functions doing the same thing, when you fix one, you’ll forget to fix another, and that’ll bite you later).

Image loading is done using UTextureFactory->FactoryCreateBinary.

Example of use can be found in Source/Editor/UnrealEd/Private/Fbx/FbxMaterialImport.cpp, within UnFbx::FFbxImporter::ImportTexture .

Where is the interaction with the Import UI? IE the user browses to a folder in the project browser and right clicks and chooses import, or clicks the import button. That mus be firing something, and that something should include the proper path yeah?

This is something I need to do as well for importing a custom mesh format, but have been unable to find any help on the forums until this post so thanks for this!

If you want to write your own importer, tear apart UFbxFactory and see how it works. Start with UFbxFactory::EnableShowOption(), it enables import ui.

In my case I was calling existing factories and did not need to interact with import ui at all (rightclick/import/etc).

It might be easier to create toolbar button and then just call “FDesktopPlatformModule::Get()->OpenFileDialog()” from it.

When in doubt, read source code.

My texture source isn’t a file, rather it’s dynamically generated image data. Bmp is the closest format to raw, so it might as well be that. It just needs a few characters the front. Then I can use the existing code, yes.

Encoding in-memory image data into any file format in order to create a texture is almost certainly the wrong way to do it.

In 3 seconds google search located this:

Is this what you wanted?

That does create a dynamic texture but I’m past that and need to save it as an asset. That’s sorted too, but I’m trying out the same import path as you in order to get it to generate mip maps. I haven’t found where the mips are generated yet, but I should have some time to look further into it this week hopefully. I probably won’t need the bmp header injection in the end but I need to get a little further along so I can focus on some other things and come back to this part of it later. :slight_smile: