3d model viewer for Monogame [ver 0.6]

MGCB should properly support linked files. https://github.com/MonoGame/MonoGame/issues/5109
With that you could fix the texture issue here.

the issue lays therein that i can’t make mgcb output the files in the output directory if i use absolute paths, so i have to copy the files to the local directory to work with relative paths.

If the output directory is relative it will create some relative output folders which are somewhere between the viewer and the source file directory.

But I can’t know what references the file has beforehand.

@kosmonautgames

I had the same issue. and solved it with a custom ContentManager.

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Microsoft.Xna.Framework.Content;

namespace TableEditor.Models.AetherProject
{
    class ProjectContentManager: ContentManager
    {
        Dictionary<string, object> loadedAssets = new Dictionary<string, object>();
        List<IDisposable> disposableAssets = new List<IDisposable>();
        private string _projectLocation = "";

        
        public ProjectContentManager(IServiceProvider serviceProvider, string rootDirectory): base(serviceProvider, rootDirectory)
        {
        }
        
        public ProjectContentManager(IServiceProvider serviceProvider): base(serviceProvider)
        {
        }

        protected override Stream OpenStream(string assetName)
        {
            Stream stream;
            if (Path.IsPathRooted(assetName))
            {
                var assetPath = Path.Combine(RootDirectory, assetName);
                stream = File.OpenRead(assetPath + ".xnb");
            }
            else
            {
                stream = base.OpenStream(assetName);
            }
            
            return stream;
        }
        
        public override T Load<T>(string assetName)
        {
            if (loadedAssets.ContainsKey(assetName))
                return (T)loadedAssets[assetName];

            string callerLocation   = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location) + "\\";
            //string hostLocation     = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\";
            string currentLocation  = Directory.GetCurrentDirectory();
            string projectLocation = _projectLocation;

            string assetPath = assetName; //default value
            if(File.Exists(Path.Combine(callerLocation, RootDirectory, assetName) + ".xnb"))
                assetPath = Path.Combine(callerLocation, RootDirectory, assetName);
            else if (File.Exists(Path.Combine(currentLocation, RootDirectory, assetName) + ".xnb"))
                assetPath = Path.Combine(currentLocation, RootDirectory, assetName);
            else if (File.Exists(Path.Combine(projectLocation, RootDirectory, assetName) + ".xnb"))
                assetPath = Path.Combine(projectLocation, RootDirectory, assetName);
            
            T asset = ReadAsset<T>(assetPath, RecordDisposableAsset);
            loadedAssets.Add(assetName, asset);

            return asset;
        }
        
        public override void Unload()
        {
            foreach (IDisposable disposable in disposableAssets)
                disposable.Dispose();

            loadedAssets.Clear();
            disposableAssets.Clear();
        }
        
        void RecordDisposableAsset(IDisposable disposable)
        {
            disposableAssets.Add(disposable);
        }

        public IDisposable UnloadAsset(string assetName)
        {   
            if(!loadedAssets.ContainsKey(assetName))
                return null;
            
            object asset = loadedAssets[assetName];            
            loadedAssets.Remove(assetName);

            if (asset is IDisposable)
            {
                if (disposableAssets.Contains((IDisposable)asset))
                    disposableAssets.Remove((IDisposable)asset);
            }

            return asset as IDisposable;
        }
    }
}

@nkast the content loader is fine, I think, it’s mgcb.exe that’s the problem

And i can’t just stream in the files since I need to generate tangent frames for the models, so I need mgcb

Can you give an example?
mgcb output the texture.xnb on a different directory than model.xnb?

Or is it just that the xnb is generated on a different directory than the running app?

I’ve written about it here typical/working command line inputs for MGCB?

What i want:

read a file from an absolute path and output the processed files in a output folder.

What happens:

If the absolute path of the source is on a different partition the generated .xnb file will be in the source folder
If the absolute path of the source is on the same partition the generated .xnb file will be in some new folder which, and now comes the great part, will generate a new folder somewhere above the working directory with a relative path from the last path that working and source directory share. I thought i was going crazy.

Example:
My program executes from here:
C:\Users\Me\Documents\Visual Studio 2015\Projects\HelperSuite\HelperSuite\bin\Windows\x86\Debug

if I process the file
C:\Users\Me\Documents\Visual Studio 2015\Projects\DeferredCascadedShadowMaps\GameThumbnail.png

The resulting processed file will be created here
C:\Users\Me\Documents\Visual Studio 2015\Projects\HelperSuite\HelperSuite\bin\DeferredCascadedShadowMaps\GameThumbnail.xnb

if it’s any help, for mgcb I set the Process.StartInfo.WorkingDirectory = SourcePath.

From there, I always have the output rooted to the source ( OutputDir = SourcePath\Content\ )
The ProjectContentManager will load absolute paths or search for the .xnb in the CurrentDirectory and _projectLocation (=SourcePath?).

The callerLocation is for Modules that load their own content.

edit
I always have the .mgcb file in the SourcePath, so maybe StartInfo.WorkingDirectory has to point to the .mgcb.

Actually, my OutputDir is @SourcePath\…\Content\

1 Like

Whoaaaaaaaaaaaa! That’s one good lookin’ gif!

Buuut… there’s something I should mention. That animation I made, I deliberately made the head bone scale up and down quite extremely to test scaling. Would your program support that?

well you seem to be right then, the animation pipeline does not support scaling correctly.

That said it is possible that something went wrong during the export, but I would think the problem lays with the better skinned sample

Yeah, I’ve looked into it and I think the latter is the case. I have modified my copy of BetterSkinned to at least process scaling in the pipeline correctly, but either I did something wrong at that step, or at the actual rendering step, because, while the scaling does show up, it’s heavily distorted.

If you’re planning on modifying your BetterSkinned, be sure to watch out for any instance where it sets scaling to a default of 1. There are many instances where that 1 multiplier is hard coded in. Come to think of it, it’s entirely possible I just missed one of those instances on my end when I modified it.

interestingly I found that some animations look completely distorted when I import them into blender and export them right away, without changing anything. Strange

Even worse: I exported an animated mesh from blender and imported it again and suddenly it had more bones and the animation wasn’t the same? Wth

This process can be repeated infinitely. Not good.

Is ur IBL cubemap prebaked?

When I load a model, it says it has been converted, but nothing happens.
So I tried with the fish your pointed upper, and same thing, mgcb does its job, but the sphere is still there. Have I missed something ?
Whenever I close the app, windows says it has ceased functioning.
If I launch visual as the debugger, it says:

An unhandled exception of type ‘System.TypeInitializationException’ occurred in MonoGame.Framework.dll

Additional information: an exception has been thrown by the type initiator of ‘Microsoft.Xna.Framework.Audio.SoundEffect’.

yes

Oh, that sucks. I uploaded a new version which produces a log file inside the .exe folder (log.txt). Maybe that can help.

(version 0.4)

I’ve also added support for objects that were previously not handled well.
This one didn’t work before and it had distorted materials when it finally did. Now it’s correct.

and this model didn’t work either, because it has no normals. So I generate the normals inside the pixel shader for that case (not the same uboat as the one mentioned earlier)

Here is a bonus with the stormtrooper with metal armor (metallic set to 1, no metallic texture) just because i think it looks great

2 Likes

I have tried the latest version to load the fish, the log says it could not find the dll:

H:/________MonoGame/Monogame Modelviewer5/Content/mgcb/MGSkinnedAnimationAux.dll

Maybe a problem with relative names in the references ?
The file is indeed in the folder as i’ve not touched any file.

I have also tried with buddha, which I had to convert to the new fbx format as MG Pipeline tool said it was a too old format to build it.

H:/________MonoGame/Monogame Modelviewer5/buddhaConverted.fbx
H:/________MonoGame/Monogame Modelviewer5/buddhaConverted.fbx: error: Failed to create processor 'AnimationProcessor’Build 0 succeeded, 1 failed.Time elapsed 00:00:04.19.

Even with a simple plane.fbx it fails, with the same error about the creation of ‘AnimationProcessor’.

just to confirm my suspicion can you start the model viewer from c:/ ?

EDIT: Nvm, i’ve tried myself and it works from any directory on my system.

3rd party tool to baked or capture and baked under ur application?

amd cubemapgen

Why are you asking

o… coz im looking for method to do impotant sampling in on captured cubemap.

From c:, at the root:

mgcb finished with exit code = 1: Std output:
Build started 01/02/2017 17:17:03Failed to load assembly ‘C:/Monogame Modelviewer5/Content/mgcb/MGSkinnedAnimationAux.dll’: Impossible de charger le fichier ou l’assembly ‘file:///C:\Monogame Modelviewer5\Content\mgcb\MGSkinnedAnimationAux.dll’ ou une de ses d‚pendances. L’op‚ration n’est pas prise en charge. (Exception de HRESULT : 0x80131515)Failed to load assembly ‘C:/Monogame Modelviewer5/Content/mgcb/MGSkinnedAnimationPipeline.dll’: Impossible de charger le fichier ou l’assembly ‘file:///C:\Monogame Modelviewer5\Content\mgcb\MGSkinnedAnimationPipeline.dll’ ou une de ses d‚pendances. L’op‚ration n’est pas prise en charge. (Exception de HRESULT : 0x80131515)C:/Monogame Modelviewer5/fish.fbxC:/Monogame Modelviewer5/fish.fbx: error: Failed to create processor 'AnimationProcessor’Build 0 succeeded, 1 failed.Time elapsed 00:00:00.69.

EDIT: Maybe a clue, I only have .NET 4.0, 4.5.1, 4.6,4.6.1. Not 4.5.0. Should’nt it work with the 4.5.1 or above ?
Windows7 x64 / VS 2K13.