Katalyst6 / CSL.NetworkExtensions

11 stars 9 forks source link

How to directly load FBX files into the game #8

Open boformer opened 9 years ago

boformer commented 9 years ago

I told you once that I have some code you might be interested in:

// the default assets import path
var path = Path.Combine(DataLocation.addonsPath, "Import");
var modelName = "Test.fbx";

// load model
using ColossalFramework.Importers;
using ColossalFramework.IO;

var importer = new SceneImporter();
importer.filePath = Path.Combine(path, modelName);
importer.importSkinMesh = true;
var importedModel = importer.Import();

// load textures
var results = new AssetImporterTextureLoader.ResultType[]
{
    AssetImporterTextureLoader.ResultType.RGB,
    AssetImporterTextureLoader.ResultType.XYS,
    AssetImporterTextureLoader.ResultType.ACI
};
AssetImporterTextureLoader.LoadTextures(null, importedModel, results, path, modelName, false);

Now the problem is, this model uses a default shader which does not support rotating and scaling, which is important for net segment meshes.

This happens when you apply the existing mesh and material from importedModel to a net segment:

Bridge

What you can do is: Apply the mesh and apply the single textures to the material of the net segment:

Bridge

Now the scaling and rotating works correcly, but the texture mapping does not.

Here is the rest of my code:

if (importedModel == null)
{
    return;
}

var component = importedModel.GetComponent<MeshFilter>();
if (component == null)
{
    return;
}

// This is the imported Mesh
segmentMesh = RuntimeMeshUtils.CopyMesh(component.sharedMesh);

NetInfoHook.OnPreInitialization += delegate(NetInfo info)
{
    if (info.name == "Medium Road Bridge")
    {
        if (info.m_segments.Length == 2)
        {
            // this is the bridge segment
            var segment = info.m_segments[1];

            segment.m_mesh = segmentMesh;

            var renderer = importedModel.GetComponent<Renderer>();

            if (renderer != null)
            {
                segment.m_material.SetTexture("_MainTex", renderer.sharedMaterial.GetTexture("_MainTex"));
                segment.m_material.SetTexture("_XYSMap", renderer.sharedMaterial.GetTexture("_XYSMap"));
                segment.m_material.SetTexture("_APRMap", renderer.sharedMaterial.GetTexture("_APRMap"));
                // if you uncomment this line, your segment will look like in the first image.
                // segment.m_material.shader = renderer.sharedMaterial.shader;
            }
        }
    }
};

NetInfoHook is my own little class. It's obvious what it does.

boformer commented 9 years ago

The shader applies a texture (but not the one I supplied) to the bridge segment. It looks like the default asphalt texture. The texture is applied "from above" and ignores the supplied UV map. Bad for bridges, but maybe enough for road segments, which are usually flat surfaces.

If you manage it to replace the used texture, you can work with it:

Asphalt

Maybe this is a problem that only affects bridge segments. Who knows...