[SOLVED] Custom pipeline processor error

I have a custom pipeline processor for processing a model and adding a custom tag that sets a bounding box etc.

I recently tried adding a couple more features to my tag and ran into an issue.

The problem is when I try to read / reference the textures of the model:

The exact error I get is:

<blah>/Content/models/dude/dude.fbx : error : Importer 'TextureImporter' had unexpected failure!
Microsoft.Xna.Framework.Content.ContentLoadException: TextureImporter failed to load  <blah>/Content/bin/DesktopGL/models/head_0.xnb

The xnb file seems to be in the correct location, so that’s not the problem. Also, I am using the model that comes with the skinning / animation sample from MS (the dude.fbx model). All the textures for that model are TGA files (if that matters).

The exact code I am using to try and reference the texture in my processor is:

Texture2D myTexture = context.BuildAndLoadAsset<TextureContent, Texture2D>(((BasicMaterialContent)meshPart.Material).Texture, "TextureProcessor", null, "TextureImporter");

I am not sure if the issue is the TGA texture file, or the way I am trying to reference it.

FYI meshPart.Material.Texture is of type ExternalReference<TextureContent>.

I am also currently running the 3.6 dev version of Monogame from the build server. It’s not the most current version, but it’s only a couple weeks old at the most.

Any ideas on how I can get past this problem? This has really gotten me stuck…

Thanks!

No one has any suggestions or ideas on how I could solve this?

I am pretty stuck on this one…

Thanks!

you should provide more information on the exception itself, stacktraces and base exception would be helpful.

A practical habit I tend to do in catch blocks is

Exception rootCause = thrownException.GetBaseException();

@raizam Thanks for the response.

The exception is being thrown from the context.BuildAndLoadAsset call, and I am not trapping it in any way. Here’s the full stack trace I am getting:

Microsoft.Xna.Framework.Content.ContentLoadException: TextureImporter failed to load 'D:/Games/MonogameTest/Content/bin/DesktopGL/models/head_0.xnb'
at Microsoft.Xna.Framework.Content.Pipeline.TextureImporter.Import(String filename, ContentImporterContext context)
at Microsoft.Xna.Framework.Content.Pipeline.ContentImporter`1.Microsoft.Xna.Framework.Content.Pipeline.IContentImporter.Import(String filename, ContentImporterContext context)
at MonoGame.Framework.Content.Pipeline.Builder.PipelineManager.ProcessContent(PipelineBuildEvent pipelineEvent) 

Thanks!

Well I’m still a noob with XNA/Monogame, never done any content pipeline extension, but still trying to help (and learn):slight_smile:

Maybe you can log the exception this way:

        try
        {
            Texture2D myTexture = context.BuildAndLoadAsset<TextureContent, Texture2D>(((BasicMaterialContent)meshPart.Material).Texture, "TextureProcessor", null, "TextureImporter");
        }
        catch(Exception ex)
        {
            context.Logger.LogImportantMessage("Root cause: {0}", ex.GetBaseException());
        }

Also, why do you need to load a Texture2D instance from the ContentProcessor?
Maybe you need something like the AddDependency method?

context.AddDependency(((BasicMaterialContent)meshPart.Material).Texture)

keep in mind that I have no idea what I’m talking about :smile_cat:

@raizam

Your code above is basically just trapping the same exception and re-logging it, since it prints the same thing I listed above, but just twice.

I believe the problem is somehow in the TextureImporter, and unfortunately the code there does not seem to be logging any more details about the error, so it’s not clear why the TextureImporter is failing. I was hoping someone who was more familar with the TextureImporter, or who previously ran into a similar problem might be able to help.

The reason I need to load the texture is to setup my own effects for each meshpart in the model, and set the texture in the custom effect (similar to how it’s done with BasicEffect right now).

I am not sure what context.AddDependency does… so if you can shed more light on it, that would be great! :slight_smile:

Thanks!

about the AddDependency it says:

Adds a dependency to the specified file. This causes a rebuild of the file, when modified, on subsequent incremental builds.
Remarks: Do not call this method for data that has already been loaded by an importer or passed to the BuildAndLoadAsset method. It is only required for additional files needing to be read by the processor.

What I meant is that rather than loading the Texture2D, you may just need to specify a reference to it.
My understanding is that a Texture2D should be loaded by the ContentLoader at runtime, not the Processor.

@raizam I am pretty new to game developement and Monogame myself, and even newer to the context pipeline stuff, so I could be wrong… but I believe the way to specify a reference to something in a custom pipeline processor would be to reference it as an ExternalReference type.

However, the problem is (If I am not mistaken), is that at some point that external reference, still needs to be loaded / built (in this case when creating the final Effect instance), so the problem might still surface then when it tries to actually load the texture.

I guess I am a little confused about some of the steps of a pipeline processor. Lets say that I create my Effect instance and set the Tag to point to it. Since the effect instance is also being used by the actual game code (and not just pipeline tool), I want to set the texture reference in the Effect to be a Texture2D and not an ExternalReference.

If what you said is true and I should be using an external reference to the texture and not loading it now, when would I create my effect instance and set the actual texture in it (as opposed to just a reference to the texture), if it’s not during the pipeline processor stage?

I can’t seem to find a more indepth tutorial on creating custom pipeline processors that go into these levels of detail. I’ve found very basic ones that helped me get to the point I am at now, but I am stuck now and can’t seem to move forward into more advanced / tricky areas.

Thanks!

I guess you have probably seen the What is the Content Pipeline? doc from msdn.

The processor is supposed to output something that can be serialized into a xnb file. I don’t think this is what you are looking for.

From my understanding, you have made a HLSL shader that requires a texture input. You can just add your .fx file to the Content.mgcb using the GUI. From there you can load it as a Effect myEffect = Content.Load<Effect>("effectname")

Now your effect takes a texture input. So my guess is that you are looking for a way to know which texture to assign given a ModelMesh ?

@raizam That is correct. You can load the effect at runtime and assign it then, but I believe it’s more optimal to do it during the pipeline processing.

Yes, I basically need to assign the textures to each meshpart for each instance of the effect. I use effect as the example here, but there may be other instances where I might want to store the texture for each meshpart during pipeline processing (so not necessarily an effect), so will need to solve the same problem there.

I am not sure how to fix this. I may have to download the Monogame source code and see if I can add some debugging output to the TextureImporter to hopefully catch what the problem is.

@raizam If you’re still interested… I figured this out. It seems you can’t load the xnb during pipeline processing using an importer, since it has already been imported (hence being an xnb).

So when I was trying to load the actual texture using the ExternalReference, the importer was failing, since the file being references was not in it’s raw format.

There might be another way to read an already imported (i.e. in it’s xnb format) asset in the processor, but I am not sure what that way is.

I ended up solving my problem by creating an intermediate Content class and creating a Writer that serialized the info out, and then a Reader that de-serialized it and created the runtime class in the game. The de-serializer was able to read the ExternalReference texture using the ContentReader.