(This will be a little brief. A fuller treatment will be given at some point in the future.)

FbxSharp[nuget] is a pure C# library for loading FBX files. ChamberLib [nuget] is a cross-platform library for making 3d games a little more easily, the beginnings of a Game engine. Naturally, these two ought to be usable together.

FbxSharp's object model is patterned after that of the FBX SDK. It has a much richer object model than what is typically needed for video games and other real-time graphics applications.

ChamberLib has an interface named IModel, which represents a 3d model. It has methods for drawing the model, setting lighting parameters, texture map, bone transformations for skinned models, and a few other things. Different subsystems will have corresponding classes that implement the interface. (Currently, the OpenTK subsystem is the only one implemented. It has a Model class that draw using OpenTK/OpenGL. But the details are not important for this tutorial.)

The task at hand is to translate from FbxSharp's expansive object format to ChamberLib's simplified and streamlined format. The ChamberLib.FbxSharp [nuget] library does just that. Just instantiate an FbxModelImporter and pass the ImportModel method to your content importer, like so:

var importer =
    new BuiltinContentImporter(                         // resolve builtin resources
        new ContentImporter(
            new FbxModelImporter().ImportModel,         // model importer
            new BasicTextureImporter().ImportTexture,   // texture importer
            new GlslShaderImporter().ImportShaderStage, // shader importer
            null,                                       // font importer
            null,                                       // song importer
            null));                                     // sound effect importer

Now, pass the importer to the subsystem's constructor:

var subsystem = new OpenTKSubsystem(3, 3,
                        onLoadMethod: Load
                        onRenderFrameMethod: Draw,
                        contentImporter: importer);

Next, create the function that will load the model from the file. This is the same Load method we just referred to in the creation of the subsystem.

public static void Load()
{
    model = subsystem.ContentManager.LoadModel("model.fbx");
    model.SetAmbientLightColor(new Vector3(0.3f, 0.3f, 0.3f));
    model.SetDirectionalLight(_light, 0);
}

We'll also need to define the light source, and provide a field to store the model:

static IModel model;
static ChamberLib.DirectionalLight _light =
    new ChamberLib.DirectionalLight(
        direction: new Vector3(-1, -1, 0).Normalized(),
        diffuseColor: new Vector3(0.9f, 0.8f, 0.7f),
        specularColor: Vector3.Zero,
        enabled: true);

Next, create the function that will draw the model:

public static void Draw(GameTime gameTime)
{
    var id = Matrix.Identity;
    subsystem.Renderer.DrawLine (Vector3.UnitX, id, view, projection, Vector3.Zero, Vector3.UnitX);
    subsystem.Renderer.DrawLine (Vector3.UnitY, id, view, projection, Vector3.Zero, Vector3.UnitY);
    subsystem.Renderer.DrawLine (Vector3.UnitZ, id, view, projection, Vector3.Zero, Vector3.UnitZ);
    var world = Matrix.CreateScale (0.005f);
    model.Draw (world, view, projection);
}

The version of Blender used for the example seems to have a curious habit of increasing the scale of the model by 100, so it has to be re-scaled by 0.01 when drawing (plus an additional amount just to get it the right size, bringing the final scaling factor to 0.005). If you have similar troubles for a different model, you can adjust the scaling factor here to whatever you need.

Next, we'll need to define a pair of transformations, the view and the projection, that will correctly position the model within the cameras view-space, and then transfer it from 3D coordinates to the 2D screen. These matrices are used by the Draw method.

// back in the Main method
view = Matrix.CreateLookAt (new Vector3 (2, 1.5f, -4),
    Vector3.Zero, Vector3.UnitY);
projection = Matrix.CreateOrthographic (6, 4, 0.25f, 10);

Finally, we need to tell the subsystem to start running:

subsystem.Run ();

This will start up the game loop. First, it will call our Load method, and then it will repeatedly call Draw, until we close the window. This is the minimum needed to load and render a 3D model on the screen. This is just enough to get started with. Additional work will be required to move the, model, animate it, or provide input from the user.

ChamberLib.FbxSharp.Example

Here's the full source code listing:

using System;
using ChamberLib.OpenTK;
using ChamberLib.Content;

namespace ChamberLib.FbxSharp.Example
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            importer =
                new BuiltinContentImporter(                     // resolve builtin resources
                    new ContentImporter(
                        new FbxModelImporter().ImportModel,         // model importer
                        new BasicTextureImporter().ImportTexture,   // texture importer
                        new GlslShaderImporter().ImportShaderStage, // shader importer
                        null,                                       // font importer
                        null,                                       // song importer
                        null));                                     // sound effect importer


            subsystem = new OpenTKSubsystem(
                3, 3,
                onLoadMethod: Load,
                onRenderFrameMethod: Draw,
                contentImporter: importer);

            view = Matrix.CreateLookAt (new Vector3 (2, 1.5f, -4),
                Vector3.Zero, Vector3.UnitY);
            projection = Matrix.CreateOrthographic (6, 4, 0.25f, 10);

            subsystem.Run ();
        }

        static IContentImporter importer;
        static ISubsystem subsystem;
        static Matrix view;
        static Matrix projection;
        static IModel model;
        static ChamberLib.DirectionalLight _light =
            new ChamberLib.DirectionalLight(
                direction: new Vector3(-1, -1, 0).Normalized(),
                diffuseColor: new Vector3(0.9f, 0.8f, 0.7f),
                specularColor: Vector3.Zero,
                enabled: true);

        public static void Load()
        {
            model = subsystem.ContentManager.LoadModel("model.fbx");
            model.SetAmbientLightColor(new Vector3(0.3f, 0.3f, 0.3f));
            model.SetDirectionalLight(_light, 0);
        }

        public static void Draw(GameTime gameTime)
        {
            var id = Matrix.Identity;
            subsystem.Renderer.DrawLine (Vector3.UnitX, id, view, projection, Vector3.Zero, Vector3.UnitX);
            subsystem.Renderer.DrawLine (Vector3.UnitY, id, view, projection, Vector3.Zero, Vector3.UnitY);
            subsystem.Renderer.DrawLine (Vector3.UnitZ, id, view, projection, Vector3.Zero, Vector3.UnitZ);
            var world = Matrix.CreateScale (0.005f);
            model.Draw (world, view, projection);
        }

    }
}

You can find all the project files here:
https://github.com/izrik/ChamberLib.FbxSharp.Example