Search code examples
c#androidmonogame

Monogame android: How to load XNB model from stream or web service?


I am working on Monogame for Xamarin Android project. Anyone know how to load a XNB model which was created from a web service? Basically my web service will return a XNB file and Android device should be able to get that file to display 3D model instantly. I know how to load static XNB model from Assets Content folder but do not know how to load it from stream or external web service, something like this:

protected override void LoadContent()
{            
     spriteBatch = new SpriteBatch(GraphicsDevice);
     myModel = Content.Load<Model>("http://mywebservice.com/getXNBModel/1/");
}

Solution

  • I have ended up creating new class derived from ContentManager:

    class XNBContentManager : ContentManager
    {
            class FakeGraphicsService : IGraphicsDeviceService
            {   
                public FakeGraphicsService(GraphicsDevice graphicDevice)
                {
                    GraphicsDevice = graphicDevice;
                }
    
                public GraphicsDevice GraphicsDevice { get; private set; }
    
    #pragma warning disable 67
                public event EventHandler<EventArgs> DeviceCreated;
                public event EventHandler<EventArgs> DeviceDisposing;
                public event EventHandler<EventArgs> DeviceReset;
                public event EventHandler<EventArgs> DeviceResetting;
    #pragma warning restore 67
            }
    
            class FakeServiceProvider : IServiceProvider
            {
                GraphicsDevice _graphicDevice;
                public FakeServiceProvider(GraphicsDevice graphicDevice)
                {
                    _graphicDevice = graphicDevice;
                }
    
                public object GetService(Type serviceType)
                {
                    if (serviceType == typeof(IGraphicsDeviceService))
                        return new FakeGraphicsService(_graphicDevice);
    
                    throw new NotImplementedException();
                }
            }
    
            private readonly MemoryStream _xnbStream;
    
            public XNBContentManager(MemoryStream xnbStream, GraphicsDevice graphicDevice)
                : base(new FakeServiceProvider(graphicDevice), "Content")
            {
                _xnbStream = xnbStream;
            }
    
            protected override Stream OpenStream(string assetName)
            {
                return new MemoryStream(_xnbStream.GetBuffer(), false);
            }
     }
    

    Then use it in LoadContent method:

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        var content = new XNBContentManager(_xnbStream, this.GraphicsDevice);
        myModel = content.Load<Model>("WhateverName");
    }