Full Code of gpvigano/AsImpL for AI

master f9b3dc8a41a7 cached
142 files
1.5 MB
855.3k tokens
205 symbols
1 requests
Download .txt
Showing preview only (1,620K chars total). Download the full file or copy to clipboard to get everything.
Repository: gpvigano/AsImpL
Branch: master
Commit: f9b3dc8a41a7
Files: 142
Total size: 1.5 MB

Directory structure:
gitextract_wtwu_s1p/

├── .editorconfig
├── .gitattributes
├── .github/
│   └── ISSUE_TEMPLATE.md
├── .gitignore
├── Assets/
│   ├── AsImpL/
│   │   ├── Examples/
│   │   │   ├── 001_Import_SimpleTest.unity
│   │   │   ├── 001_Import_SimpleTest.unity.meta
│   │   │   ├── 002_Import_CustomImporter.unity
│   │   │   ├── 002_Import_CustomImporter.unity.meta
│   │   │   ├── 003_Import_URL_Test.unity
│   │   │   ├── 003_Import_URL_Test.unity.meta
│   │   │   ├── 004_Import_DestroyTest.unity
│   │   │   ├── 004_Import_DestroyTest.unity.meta
│   │   │   ├── Scripts/
│   │   │   │   ├── AsImpLSample.cs
│   │   │   │   ├── AsImpLSample.cs.meta
│   │   │   │   ├── CustomObjImporter.cs
│   │   │   │   ├── CustomObjImporter.cs.meta
│   │   │   │   ├── ImportDestroyTest.cs
│   │   │   │   ├── ImportDestroyTest.cs.meta
│   │   │   │   ├── Util/
│   │   │   │   │   ├── EditorLikeCameraController.cs
│   │   │   │   │   └── EditorLikeCameraController.cs.meta
│   │   │   │   └── Util.meta
│   │   │   └── Scripts.meta
│   │   ├── Examples.meta
│   │   ├── Resources/
│   │   │   ├── Materials/
│   │   │   │   ├── StandardCutout.mat
│   │   │   │   ├── StandardCutout.mat.meta
│   │   │   │   ├── StandardFade.mat
│   │   │   │   ├── StandardFade.mat.meta
│   │   │   │   ├── StandardOpaqueBump.mat
│   │   │   │   ├── StandardOpaqueBump.mat.meta
│   │   │   │   ├── StandardOpaqueMetallic.mat
│   │   │   │   ├── StandardOpaqueMetallic.mat.meta
│   │   │   │   ├── StandardTransparent.mat
│   │   │   │   ├── StandardTransparent.mat.meta
│   │   │   │   ├── UnlitTexture.mat
│   │   │   │   └── UnlitTexture.mat.meta
│   │   │   ├── Materials.meta
│   │   │   ├── Shaders/
│   │   │   │   ├── SimpleVertexColorsShader.shader
│   │   │   │   └── SimpleVertexColorsShader.shader.meta
│   │   │   ├── Shaders.meta
│   │   │   ├── Textures/
│   │   │   │   ├── diffuse.jpg.meta
│   │   │   │   ├── normalmap.png.meta
│   │   │   │   ├── opacity.png.meta
│   │   │   │   └── specular.png.meta
│   │   │   └── Textures.meta
│   │   ├── Resources.meta
│   │   ├── Scripts/
│   │   │   ├── Dataset/
│   │   │   │   ├── DataSet.cs
│   │   │   │   ├── DataSet.cs.meta
│   │   │   │   ├── IMaterialFactory.cs
│   │   │   │   ├── IMaterialFactory.cs.meta
│   │   │   │   ├── IShaderSelector.cs
│   │   │   │   ├── IShaderSelector.cs.meta
│   │   │   │   ├── MaterialData.cs
│   │   │   │   ├── MaterialData.cs.meta
│   │   │   │   ├── MaterialFactory.cs
│   │   │   │   ├── MaterialFactory.cs.meta
│   │   │   │   ├── ModelReferences.cs
│   │   │   │   ├── ModelReferences.cs.meta
│   │   │   │   ├── ModelUtil.cs
│   │   │   │   ├── ModelUtil.cs.meta
│   │   │   │   ├── ObjectBuilder.cs
│   │   │   │   ├── ObjectBuilder.cs.meta
│   │   │   │   ├── ShaderSelector.cs
│   │   │   │   ├── ShaderSelector.cs.meta
│   │   │   │   ├── Triangulator.cs
│   │   │   │   └── Triangulator.cs.meta
│   │   │   ├── Dataset.meta
│   │   │   ├── Editor/
│   │   │   │   ├── ObjImportWindow.cs
│   │   │   │   └── ObjImportWindow.cs.meta
│   │   │   ├── Editor.meta
│   │   │   ├── EditorUtil.cs
│   │   │   ├── EditorUtil.cs.meta
│   │   │   ├── IO/
│   │   │   │   ├── FileFilesystem.cs
│   │   │   │   ├── FileFilesystem.cs.meta
│   │   │   │   ├── IFilesystem.cs
│   │   │   │   └── IFilesystem.cs.meta
│   │   │   ├── IO.meta
│   │   │   ├── ImportOptions.cs
│   │   │   ├── ImportOptions.cs.meta
│   │   │   ├── Loaders/
│   │   │   │   ├── Loader.cs
│   │   │   │   ├── Loader.cs.meta
│   │   │   │   ├── LoaderObj.cs
│   │   │   │   ├── LoaderObj.cs.meta
│   │   │   │   ├── TextureLoader.cs
│   │   │   │   └── TextureLoader.cs.meta
│   │   │   ├── Loaders.meta
│   │   │   ├── LoadingProgress.cs
│   │   │   ├── LoadingProgress.cs.meta
│   │   │   ├── MathUtil/
│   │   │   │   ├── MathData/
│   │   │   │   │   ├── Triangle.cs
│   │   │   │   │   ├── Triangle.cs.meta
│   │   │   │   │   ├── Vertex.cs
│   │   │   │   │   └── Vertex.cs.meta
│   │   │   │   ├── MathData.meta
│   │   │   │   ├── MathUtility.cs
│   │   │   │   ├── MathUtility.cs.meta
│   │   │   │   ├── Triangulation.cs
│   │   │   │   └── Triangulation.cs.meta
│   │   │   ├── MathUtil.meta
│   │   │   ├── ModelImportInfo.cs
│   │   │   ├── ModelImportInfo.cs.meta
│   │   │   ├── MultiObjectImporter.cs
│   │   │   ├── MultiObjectImporter.cs.meta
│   │   │   ├── ObjectImporter.cs
│   │   │   ├── ObjectImporter.cs.meta
│   │   │   ├── ObjectImporterUI.cs
│   │   │   ├── ObjectImporterUI.cs.meta
│   │   │   ├── PathSettings.cs
│   │   │   └── PathSettings.cs.meta
│   │   └── Scripts.meta
│   └── AsImpL.meta
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Documentation/
│   └── AsImpL.chm
├── EXAMPLES.md
├── LICENSE.txt
├── ProjectSettings/
│   ├── AudioManager.asset
│   ├── ClusterInputManager.asset
│   ├── DynamicsManager.asset
│   ├── EditorBuildSettings.asset
│   ├── EditorSettings.asset
│   ├── GraphicsSettings.asset
│   ├── InputManager.asset
│   ├── NavMeshAreas.asset
│   ├── NetworkManager.asset
│   ├── Physics2DSettings.asset
│   ├── ProjectSettings.asset
│   ├── QualitySettings.asset
│   ├── TagManager.asset
│   ├── TimeManager.asset
│   ├── UnityAdsSettings.asset
│   └── UnityConnectSettings.asset
├── README.md
├── models/
│   ├── OBJ_test/
│   │   ├── README.txt
│   │   ├── objtest.mtl
│   │   ├── objtest_yup.obj
│   │   ├── objtest_zup.obj
│   │   ├── testBumpRefl.obj
│   │   ├── testDiffBump.obj
│   │   ├── testDiffOpacity.obj
│   │   ├── testRefl.obj
│   │   └── testTransp.obj
│   └── object_list_test.xml
└── package.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
; Used by the 'EditorConfig' VS plugin
; See http://editorconfig.org

; Use tabs preference set to 2 spaces per tab.
[*.cs]
indent_style = space
indent_size = 4
charset = utf-8-bom


================================================
FILE: .gitattributes
================================================
# .gitattributes

# Treat them as binary files for GitMerge
*.unity binary
*.prefab binary
*.asset binary

================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
  > **WARNING:** Any issue that does not follow the below template could be closed and not re-opened until the template structure is adhered to.


### Common rules 

#### Precheck

> * For proposing a new feature, please check existing open and closed issues before creating a duplicate
> * Add comment to an issue only if related to it (otherwise choose a different issue or create a new one)
> * Please do not write long text in issue title, choose a short title for the topic, then add your text to the issue body
> * For bugs, do a quick search and make sure the bug has not yet been reported
> * Finally, follow the code of conduct (at <https://github.com/gpvigano/AsImpL/blob/master/CODE_OF_CONDUCT.md>)
> 
> **Choose one of the categories below and follow the related template (fill the coosen section, delete everything else, including this text).**

### New features and suggestions

Follow the rules above and try to be as clear as possible.

### Problems & bugs

#### Environment
>Please specify:
> * version of AsImpL (Github master commit hash or at least date/hour when you downloaded it)
> * version of Unity3D (e.g. Unity 5.4.4f1)

#### Steps to reproduce

> For issues related to a specific 3D model try to identify which are the features of the model that cause the issue, or at least attach as a ZIP archive a very simple (lightweight) 3D model that has the same problem. If this is not possible you can send that model via e-mail to <gpv.code@gmail.com> with a subject starting with "*[AsImpL] 3D model-*", then you can create a related issue.

> For general bugs, attempt to recreate the issue with a simple example code and provide steps to reproduce if possible. Include code samples, errors and stacktraces if appropriate.

#### Expected behavior

> For general bugs, briefly describe what you expect should happen.

#### Current behavior

> For general bugs, briefly describe what is actually happening.



================================================
FILE: .gitignore
================================================
/[Ll]ibrary/
/[Tt]emp/
/Docs/
/[Aa]ssets/[Aa]sset[Ss]tore[Tt]ools*
/[Aa]ssets/[Pp]lugins*


# Autogenerated VS/MD solution and project files
ExportedObj/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd

# Unity3D generated meta files
*.pidb.meta
ProjectSettings/ProjectVersion.txt

# Unity3D Generated File On Crash Reports
sysinfo.txt

# System files
.DS_Store
*.swp
StyleCop*


================================================
FILE: Assets/AsImpL/Examples/001_Import_SimpleTest.unity.meta
================================================
fileFormatVersion: 2
guid: 451f9a57a3bcde1459f722853aa9e942
timeCreated: 1488539917
licenseType: Free
DefaultImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Examples/002_Import_CustomImporter.unity.meta
================================================
fileFormatVersion: 2
guid: 431088c5d11fb6149baa2652870e9a37
timeCreated: 1455004990
licenseType: Free
DefaultImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Examples/003_Import_URL_Test.unity.meta
================================================
fileFormatVersion: 2
guid: d5954e0fc8f8fac4682e7b99da510760
timeCreated: 1511337825
licenseType: Free
DefaultImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Examples/004_Import_DestroyTest.unity.meta
================================================
fileFormatVersion: 2
guid: deac6f02203a0384d918df133c20a6c7
timeCreated: 1645622189
licenseType: Free
DefaultImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Examples/Scripts/AsImpLSample.cs
================================================
using UnityEngine;

namespace AsImpL
{
    namespace Examples
    {
        /// <summary>
        /// Demonstrate how to load a model with ObjectImporter.
        /// </summary>
        public class AsImpLSample : MonoBehaviour
        {
            [SerializeField]
            protected string filePath = "models/OBJ_test/objtest_zup.obj";

            [SerializeField]
            protected string objectName = "MyObject";

            [SerializeField]
            protected ImportOptions importOptions = new ImportOptions();

            [SerializeField]
            protected PathSettings pathSettings;

            protected ObjectImporter objImporter;


            private void Awake()
            {
                filePath = pathSettings.RootPath + filePath;
                objImporter = gameObject.GetComponent<ObjectImporter>();
                if (objImporter == null)
                {
                    objImporter = gameObject.AddComponent<ObjectImporter>();
                }
            }


            protected virtual void Start()
            {
                objImporter.ImportModelAsync(objectName, filePath, null, importOptions);
            }


            private void OnValidate()
            {
                if(pathSettings==null)
                {
                    pathSettings = PathSettings.FindPathComponent(gameObject);
                }
            }

        }
    }
}


================================================
FILE: Assets/AsImpL/Examples/Scripts/AsImpLSample.cs.meta
================================================
fileFormatVersion: 2
guid: bee2f07bf5338dd42aaf5fc5283c1a66
timeCreated: 1488532022
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Examples/Scripts/CustomObjImporter.cs
================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Text;
using System.Xml.Serialization;
using UnityEngine;
using UnityEngine.UI;

namespace AsImpL
{
    /// <summary>
    /// Examples for demonstrating AsImpL features.
    /// </summary>
    namespace Examples
    {
        /// <summary>
        /// Read a configuration file and load the object listed there with their parameters and positions.
        /// </summary>
        public class CustomObjImporter : MultiObjectImporter
        {
            [Tooltip("Text for displaying the overall scale")]
            public Text objScalingText;

            [Tooltip("Configuration XML file (relative to the application data folder)")]
            public string configFile = "../object_list.xml";

            private List<ModelImportInfo> modelsToImport = new List<ModelImportInfo>();

            private void Awake()
            {
                configFile = RootPath + configFile;
            }


            protected override void Start()
            {
#if UNITY_STANDALONE
#if !UNITY_EDITOR
                string[] args = Environment.GetCommandLineArgs();

                if (args != null && args.Length > 1)
                {
                    int numImports = args.Length - 1;
                    for (int i = 0; i < numImports; i++)
                    {
                        if (args[i + 1].StartsWith("-"))
                        {
                            if (args[i + 1] == "-scale")
                            {
                                if (i + 1 < numImports)
                                {
                                    float.TryParse(args[i + 2], out defaultImportOptions.modelScaling);
                                }
                                i++;
                            }
                            continue;
                        }
                        ModelImportInfo modelToImport = new ModelImportInfo();
                        modelToImport.path = args[i + 1];
                        modelToImport.name = Path.GetFileNameWithoutExtension(modelToImport.path);
                        modelToImport.loaderOptions = new ImportOptions();
                        modelToImport.loaderOptions.modelScaling = defaultImportOptions.modelScaling;
                        modelToImport.loaderOptions.zUp = defaultImportOptions.zUp;
                        modelToImport.loaderOptions.reuseLoaded = false;
                        objectsList.Add(modelToImport);
                    }
                    configFile = "";

                    ImportModelListAsync(objectsList.ToArray());
                }
                else
#endif
                {
                    if (autoLoadOnStart)
                    {
                         Reload();
                    }
                }
#else
                Debug.Log("Command line arguments not available, using default settings.");
                Reload();
#endif
            }


            public void SetScaling(float scl)
            {
                scl = Mathf.Pow(10.0f, scl);
                objScalingText.text = "Scaling: " + scl;
                transform.localScale = new Vector3(scl, scl, scl);
            }


            protected override void OnImportingComplete()
            {
                base.OnImportingComplete();
                UpdateScene();
            }


            public void Save()
            {
                if (!allLoaded || string.IsNullOrEmpty(configFile))
                {
                    return;
                }

                UpdateObjectList();
                XmlSerializer serializer = new XmlSerializer(objectsList.GetType());
                FileStream stream = new FileStream(configFile, FileMode.Create);

                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent = true;
                settings.IndentChars = "  ";
                settings.Encoding = Encoding.UTF8;
                settings.CheckCharacters = true;

                XmlWriter w = XmlWriter.Create(stream, settings);

                serializer.Serialize(w, objectsList);
                stream.Dispose();
            }


            public void Reload()
            {
                if (string.IsNullOrEmpty(configFile))
                {
                    Debug.LogWarning("Empty configuration file path");
                    return;
                }

                try
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(List<ModelImportInfo>));
                    FileStream stream = new FileStream(configFile, FileMode.Open);
                    objectsList = (List<ModelImportInfo>)serializer.Deserialize(stream);
                    stream.Dispose();
                    UpdateScene();
                    ImportModelListAsync(modelsToImport.ToArray());
                }
                catch (IOException e)
                {
                    Debug.LogWarningFormat("Unable to open configuration file {0}: {1}", configFile, e);
                }
            }


            private void UpdateObject(GameObject gameObj, ModelImportInfo importInfo)
            {
                gameObj.name = importInfo.name;
                //game_object.transform.localScale = scale;
                if (importInfo.loaderOptions != null)
                {
                    gameObj.transform.localPosition = importInfo.loaderOptions.localPosition;
                    gameObj.transform.localRotation = Quaternion.Euler(importInfo.loaderOptions.localEulerAngles);
                    gameObj.transform.localScale = importInfo.loaderOptions.localScale;
                }
            }


            private void UpdateImportInfo(ModelImportInfo importInfo, GameObject gameObj)
            {
                importInfo.name = gameObj.name;
                if (importInfo.loaderOptions == null)
                {
                    importInfo.loaderOptions = new ImportOptions();
                }
                importInfo.loaderOptions.localPosition = gameObj.transform.localPosition;
                importInfo.loaderOptions.localEulerAngles = gameObj.transform.localRotation.eulerAngles;
                importInfo.loaderOptions.localScale = gameObj.transform.localScale;
            }


            private void UpdateObjectList()
            {
                for (int i = 0; i < transform.childCount; i++)
                {
                    Transform tr = transform.GetChild(i);
                    ModelImportInfo info = objectsList.Find(obj => obj.name == tr.name);
                    if (info != null)
                    {
                        UpdateImportInfo(info, tr.gameObject);
                    }
                }
            }


            private void UpdateScene()
            {
                modelsToImport.Clear();
                List<string> names = new List<string>();
                // add or update objects that are present in the list
                foreach (ModelImportInfo info in objectsList)
                {
                    names.Add(info.name);
                    Transform transf = transform.Find(info.name);
                    if (transf == null)
                    {
                        modelsToImport.Add(info);
                    }
                    else
                    {
                        UpdateObject(transf.gameObject,info);
                    }
                }
                // destroy objects that are not present in the list
                for (int i = 0; i < transform.childCount; i++)
                {
                    Transform tr = transform.GetChild(i);
                    if (tr.gameObject != gameObject && !names.Contains(tr.gameObject.name))
                    {
                        Destroy(tr.gameObject);
                    }
                }
            }

        }
    }
}


================================================
FILE: Assets/AsImpL/Examples/Scripts/CustomObjImporter.cs.meta
================================================
fileFormatVersion: 2
guid: 1aaecb2e4740ee44eab58edee766ade6
timeCreated: 1452761617
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Examples/Scripts/ImportDestroyTest.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace AsImpL
{
    namespace Examples
    {
        /// <summary>
        /// Demonstrate how to load and destroy a model multiple times.
        /// </summary>
        public class ImportDestroyTest : AsImpLSample
        {
            [SerializeField]
            protected float reloadInterval = 1.0f;


            protected override void Start()
            {
                importOptions.reuseLoaded = false;
                objImporter.ImportedModel += OnModelImported;
                objImporter.ImportModelAsync(objectName, filePath, null, importOptions);
            }

            private void OnModelImported(GameObject obj, string objPath)
            {
                StartCoroutine(ReloadObject(obj));
            }

            private IEnumerator ReloadObject(GameObject obj)
            {
                yield return new WaitForSecondsRealtime(reloadInterval);
                Destroy(obj);
                yield return null;
                objImporter.ImportModelAsync(objectName, filePath, null, importOptions);
                yield return null;
            }
        }
    }
}


================================================
FILE: Assets/AsImpL/Examples/Scripts/ImportDestroyTest.cs.meta
================================================
fileFormatVersion: 2
guid: a4f0318c2c384b14ca0671fa133f70fa
timeCreated: 1645622247
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Examples/Scripts/Util/EditorLikeCameraController.cs
================================================
using UnityEngine;

namespace AsImpL
{
    namespace Examples
    {
        public class EditorLikeCameraController : MonoBehaviour
        {
#if (UNITY_ANDROID || UNITY_IPHONE)
        void Awake()
        {
            Debug.LogWarning(GetType().Name + " cannot be used for mobile devices.");
        }
#endif
#if ((!UNITY_ANDROID && !UNITY_IPHONE) || UNITY_EDITOR)
            void Update()
            {
                float x = Input.GetAxis("Horizontal") * 0.1f;
                float y = 0.0f;
                float z = Input.GetAxis("Vertical") * 0.1f;

                if (Input.GetMouseButton(1))
                {
                    float rx = Input.GetAxis("Mouse Y") * 2.0f;
                    float ry = Input.GetAxis("Mouse X") * 2.0f;

                    Vector3 rot = transform.eulerAngles;
                    rot.x -= rx;
                    rot.y += ry;
                    transform.eulerAngles = rot;
                }
                if (Input.GetMouseButton(2))
                {
                    x -= Input.GetAxis("Mouse X") * 0.1f;
                    y -= Input.GetAxis("Mouse Y") * 0.1f;
                }
                z += Input.GetAxis("Mouse ScrollWheel");

                transform.Translate(x, y, z);
            }
#endif
        }
    }
}



================================================
FILE: Assets/AsImpL/Examples/Scripts/Util/EditorLikeCameraController.cs.meta
================================================
fileFormatVersion: 2
guid: c7c40d4a6f6f5aa45a056cfbe4301b66
timeCreated: 1478530910
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Examples/Scripts/Util.meta
================================================
fileFormatVersion: 2
guid: 22a5be0aa0dd0e54a80d091fe3322f33
folderAsset: yes
timeCreated: 1488543190
licenseType: Free
DefaultImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Examples/Scripts.meta
================================================
fileFormatVersion: 2
guid: 8a68e30fc3d54dd47ae5f6017cf909d0
folderAsset: yes
timeCreated: 1452774378
licenseType: Free
DefaultImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Examples.meta
================================================
fileFormatVersion: 2
guid: 77617cdd806530c47a717d997786c6ba
folderAsset: yes
timeCreated: 1486633078
licenseType: Free
DefaultImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Materials/StandardCutout.mat.meta
================================================
fileFormatVersion: 2
guid: ce02b9c55bb8b524aab575e0b3e047a5
timeCreated: 1455546091
licenseType: Free
NativeFormatImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Materials/StandardFade.mat.meta
================================================
fileFormatVersion: 2
guid: d553ada60d81dd0488389607fb6f3d35
timeCreated: 1455637853
licenseType: Free
NativeFormatImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Materials/StandardOpaqueBump.mat.meta
================================================
fileFormatVersion: 2
guid: e83baad023334524d9f56155b1c433b9
timeCreated: 1455538553
licenseType: Free
NativeFormatImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Materials/StandardOpaqueMetallic.mat.meta
================================================
fileFormatVersion: 2
guid: 26497679857597f4d82243edd29acadf
timeCreated: 1488550076
licenseType: Free
NativeFormatImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Materials/StandardTransparent.mat.meta
================================================
fileFormatVersion: 2
guid: b29f2c52b07fbca4cb8d84df828b853e
timeCreated: 1455538582
licenseType: Free
NativeFormatImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Materials/UnlitTexture.mat.meta
================================================
fileFormatVersion: 2
guid: 098032ac46e964e46875663fcdeacddd
timeCreated: 1548771631
licenseType: Free
NativeFormatImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Materials.meta
================================================
fileFormatVersion: 2
guid: 774dec663515133459e48baaf3034985
folderAsset: yes
timeCreated: 1550227278
licenseType: Free
DefaultImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Shaders/SimpleVertexColorsShader.shader
================================================
// Simple Vertex Colors shader, used when only vertex colors are available

Shader "Unlit/Simple Vertex Colors Shader" {
Properties {
  [Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull", Float) = 0 //"Off"
}

Category {
	Tags { "Queue"="Geometry" "RenderType"="Opaque" }
	Lighting Off ZWrite On Fog { Color (0,0,0,0) }
	
	BindChannels {
		Bind "Color", color
		Bind "Vertex", vertex
		Bind "TexCoord", texcoord
	}
	
	SubShader {
		Cull[_Cull]
		Pass {
		}
	}
}
}


================================================
FILE: Assets/AsImpL/Resources/Shaders/SimpleVertexColorsShader.shader.meta
================================================
fileFormatVersion: 2
guid: 93f01d2146d2cee4da1df042a12543cb
timeCreated: 1512565342
licenseType: Free
ShaderImporter:
  defaultTextures: []
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Shaders.meta
================================================
fileFormatVersion: 2
guid: 82adea7a26b85af4ca881ba138b78298
folderAsset: yes
timeCreated: 1550227289
licenseType: Free
DefaultImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Textures/diffuse.jpg.meta
================================================
fileFormatVersion: 2
guid: eead99b9b56006e4a9d7fb98b7a9886f
timeCreated: 1488550057
licenseType: Free
TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 4
  mipmaps:
    mipMapMode: 0
    enableMipMap: 1
    sRGBTexture: 1
    linearTexture: 0
    fadeOut: 0
    borderMipMap: 0
    mipMapFadeDistanceStart: 1
    mipMapFadeDistanceEnd: 3
  bumpmap:
    convertToNormalMap: 0
    externalNormalMap: 0
    heightScale: 0.25
    normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 6
  cubemapConvolution: 0
  seamlessCubemap: 0
  textureFormat: 1
  maxTextureSize: 2048
  textureSettings:
    filterMode: -1
    aniso: -1
    mipBias: -1
    wrapMode: -1
  nPOTScale: 1
  lightmap: 0
  compressionQuality: 50
  spriteMode: 0
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: 0.5, y: 0.5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaUsage: 1
  alphaIsTransparency: 0
  spriteTessellationDetail: -1
  textureType: 0
  textureShape: 1
  maxTextureSizeSet: 0
  compressionQualitySet: 0
  textureFormatSet: 0
  platformSettings:
  - buildTarget: DefaultTexturePlatform
    maxTextureSize: 2048
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
  spriteSheet:
    serializedVersion: 2
    sprites: []
    outline: []
  spritePackingTag: 
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Textures/normalmap.png.meta
================================================
fileFormatVersion: 2
guid: a0b134f9c1c11674687c93065fb2f07e
timeCreated: 1488550559
licenseType: Free
TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 4
  mipmaps:
    mipMapMode: 0
    enableMipMap: 1
    sRGBTexture: 0
    linearTexture: 0
    fadeOut: 0
    borderMipMap: 0
    mipMapFadeDistanceStart: 1
    mipMapFadeDistanceEnd: 3
  bumpmap:
    convertToNormalMap: 0
    externalNormalMap: 0
    heightScale: 0.25
    normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 6
  cubemapConvolution: 0
  seamlessCubemap: 0
  textureFormat: 1
  maxTextureSize: 2048
  textureSettings:
    filterMode: -1
    aniso: -1
    mipBias: -1
    wrapMode: -1
  nPOTScale: 1
  lightmap: 0
  compressionQuality: 50
  spriteMode: 0
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: 0.5, y: 0.5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaUsage: 1
  alphaIsTransparency: 0
  spriteTessellationDetail: -1
  textureType: 1
  textureShape: 1
  maxTextureSizeSet: 0
  compressionQualitySet: 0
  textureFormatSet: 0
  platformSettings:
  - buildTarget: DefaultTexturePlatform
    maxTextureSize: 2048
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
  spriteSheet:
    serializedVersion: 2
    sprites: []
    outline: []
  spritePackingTag: 
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Textures/opacity.png.meta
================================================
fileFormatVersion: 2
guid: 437784474ac4cf247bdc2c060fb8beec
timeCreated: 1488550526
licenseType: Free
TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 4
  mipmaps:
    mipMapMode: 0
    enableMipMap: 1
    sRGBTexture: 1
    linearTexture: 0
    fadeOut: 0
    borderMipMap: 0
    mipMapFadeDistanceStart: 1
    mipMapFadeDistanceEnd: 3
  bumpmap:
    convertToNormalMap: 0
    externalNormalMap: 0
    heightScale: 0.25
    normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 6
  cubemapConvolution: 0
  seamlessCubemap: 0
  textureFormat: -1
  maxTextureSize: 2048
  textureSettings:
    filterMode: -1
    aniso: -1
    mipBias: -1
    wrapMode: -1
  nPOTScale: 1
  lightmap: 0
  compressionQuality: 50
  spriteMode: 0
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: 0.5, y: 0.5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaUsage: 1
  alphaIsTransparency: 0
  spriteTessellationDetail: -1
  textureType: 0
  textureShape: 1
  maxTextureSizeSet: 0
  compressionQualitySet: 0
  textureFormatSet: 0
  platformSettings:
  - buildTarget: DefaultTexturePlatform
    maxTextureSize: 2048
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
  - buildTarget: Standalone
    maxTextureSize: 2048
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
  - buildTarget: Android
    maxTextureSize: 2048
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
  spriteSheet:
    serializedVersion: 2
    sprites: []
    outline: []
  spritePackingTag: 
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Textures/specular.png.meta
================================================
fileFormatVersion: 2
guid: 554f46dfdb7e37049aae3530dfd2913c
timeCreated: 1488550057
licenseType: Free
TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 4
  mipmaps:
    mipMapMode: 0
    enableMipMap: 1
    sRGBTexture: 1
    linearTexture: 0
    fadeOut: 0
    borderMipMap: 0
    mipMapFadeDistanceStart: 1
    mipMapFadeDistanceEnd: 3
  bumpmap:
    convertToNormalMap: 0
    externalNormalMap: 0
    heightScale: 0.25
    normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 6
  cubemapConvolution: 0
  seamlessCubemap: 0
  textureFormat: 1
  maxTextureSize: 2048
  textureSettings:
    filterMode: -1
    aniso: -1
    mipBias: -1
    wrapMode: -1
  nPOTScale: 1
  lightmap: 0
  compressionQuality: 50
  spriteMode: 0
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: 0.5, y: 0.5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaUsage: 1
  alphaIsTransparency: 0
  spriteTessellationDetail: -1
  textureType: 0
  textureShape: 1
  maxTextureSizeSet: 0
  compressionQualitySet: 0
  textureFormatSet: 0
  platformSettings:
  - buildTarget: DefaultTexturePlatform
    maxTextureSize: 2048
    textureFormat: -1
    textureCompression: 1
    compressionQuality: 50
    crunchedCompression: 0
    allowsAlphaSplitting: 0
    overridden: 0
  spriteSheet:
    serializedVersion: 2
    sprites: []
    outline: []
  spritePackingTag: 
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources/Textures.meta
================================================
fileFormatVersion: 2
guid: b082fccb83cdc744c88032b4462ae698
folderAsset: yes
timeCreated: 1550227267
licenseType: Free
DefaultImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Resources.meta
================================================
fileFormatVersion: 2
guid: 5677e9ac29b1e154f91a00612aacf1e8
folderAsset: yes
timeCreated: 1455020463
licenseType: Free
DefaultImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Dataset/DataSet.cs
================================================
using UnityEngine;
using System.Collections.Generic;

namespace AsImpL
{
    /// <summary>
    /// Data set for storing data in a neutral format for a generic model
    /// </summary>
    /// <remarks>This should be completed and extended to support more formats.</remarks>
    /// TODO: Classes to hold data for internal hierarchy should be defined.
    public class DataSet
    {
        /// <summary>
        /// List of objects
        /// </summary>
        public List<ObjectData> objectList = new List<ObjectData>();

        /// <summary>
        /// List of vertices
        /// </summary>
        public List<Vector3> vertList = new List<Vector3>();

        /// <summary>
        /// List of texture coordinates (UV)
        /// </summary>
        public List<Vector2> uvList = new List<Vector2>();

        /// <summary>
        /// List of normals
        /// </summary>
        public List<Vector3> normalList = new List<Vector3>();

        /// <summary>
        /// List of colors
        /// </summary>
        public List<Color> colorList = new List<Color>();

        // naming index for unnamed group (e.g. "Unnamed-1")
        private int unnamedGroupIndex = 1;
        private ObjectData currObjData;

        private FaceGroupData currGroup;

        private bool noFaceDefined = true;


        /// <summary>
        /// Name of the current group.
        /// </summary>
        public string CurrGroupName
        {
            get
            {
                return currGroup != null ? currGroup.name : "";
            }
        }

        /// <summary>
        /// Check if there is no vertex defined.
        /// </summary>
        public bool IsEmpty
        {
            get
            {
                return vertList.Count == 0;
            }
        }


        /// <summary>
        /// Get a string key based on the given face indices
        /// </summary>
        /// <param name="fi">face indices structure</param>
        /// <returns></returns>
        public static string GetFaceIndicesKey(FaceIndices fi)
        {
            return fi.vertIdx.ToString() + "/" + fi.uvIdx.ToString() + "/" + fi.normIdx.ToString();
        }


        /// <summary>
        /// Change the material name to be compliant with Unity material asset naming.
        /// </summary>
        /// <param name="mtlName">original material name</param>
        /// <returns>Returns the name modified to be compliant with Unity material asset naming.</returns>
        public static string FixMaterialName(string mtlName)
        {
            return mtlName
                .Replace(':', '_')
                .Replace('\\', '_')
                .Replace('/', '_')
                .Replace('*', '_')
                .Replace('?', '_')
                .Replace('<', '_')
                .Replace('>', '_')
                .Replace('|', '_');
        }


        /// <summary>
        /// Constructor: create data lists and initialize the default object.
        /// </summary>
        public DataSet()
        {
            ObjectData d = new ObjectData();
            d.name = "default";
            objectList.Add(d);
            currObjData = d;

            FaceGroupData g = new FaceGroupData();
            g.name = "default";
            d.faceGroups.Add(g);
            currGroup = g;
        }


        /// <summary>
        /// Add and initialize a new object.
        /// </summary>
        /// <param name="objectName">name of the new object</param>
        public void AddObject(string objectName)
        {
            //Debug.Log("Adding new object " + name + ". Current is empty: " + isEmpty);
            string currentMaterial = currObjData.faceGroups[currObjData.faceGroups.Count - 1].materialName;

            if (noFaceDefined) objectList.Remove(currObjData);

            ObjectData objData = new ObjectData();
            objData.name = objectName;
            objectList.Add(objData);

            FaceGroupData grp = new FaceGroupData();
            grp.materialName = currentMaterial;
            grp.name = "default";
            objData.faceGroups.Add(grp);

            currGroup = grp;
            currObjData = objData;
        }


        /// <summary>
        /// Add and initialize a new group and add it to the current object.
        /// </summary>
        /// <param name="groupName">name of the new group</param>
        public void AddGroup(string groupName)
        {
            string currentMaterial = currObjData.faceGroups[currObjData.faceGroups.Count - 1].materialName;

            if (currGroup.IsEmpty) currObjData.faceGroups.Remove(currGroup);
            FaceGroupData grp = new FaceGroupData();
            grp.materialName = currentMaterial;
            if (groupName == null)
            {
                groupName = "Unnamed-" + unnamedGroupIndex;
                unnamedGroupIndex++;
            }
            grp.name = groupName;
            currObjData.faceGroups.Add(grp);
            currGroup = grp;
        }


        /// <summary>
        /// Set a new material name to the current group (add a group if not yet added).
        /// </summary>
        /// <param name="matName">name of the new material</param>
        /// TODO: do not split by materials if there is only one material
        public void AddMaterialName(string matName)
        {
            if (!currGroup.IsEmpty) AddGroup(matName);
            if (currGroup.name == "default") currGroup.name = matName;
            currGroup.materialName = matName;
        }


        /// <summary>
        /// Add a vertex to the global vertex list
        /// </summary>
        /// <param name="vertex">new vertex</param>
        public void AddVertex(Vector3 vertex)
        {
            vertList.Add(vertex);
        }


        /// <summary>
        /// Add a texture coordinate (U,V) to the global list
        /// </summary>
        /// <param name="uv">texture coordinate (U,V)</param>
        public void AddUV(Vector2 uv)
        {
            uvList.Add(uv);
        }


        /// <summary>
        /// Add a new normal to the global list
        /// </summary>
        /// <param name="normal">normal</param>
        public void AddNormal(Vector3 normal)
        {
            normalList.Add(normal);
        }


        /// <summary>
        /// Add a new color to the global list
        /// </summary>
        /// <param name="color">color</param>
        public void AddColor(Color color)
        {
            colorList.Add(color);
            currObjData.hasColors = true;
        }


        /// <summary>
        /// Add a new face indices entry to the current faces group
        /// </summary>
        /// <param name="faceIdx">new vertex indices</param>
        public void AddFaceIndices(FaceIndices faceIdx)
        {
            noFaceDefined = false;
            currGroup.faces.Add(faceIdx);
            currObjData.allFaces.Add(faceIdx);
            if (faceIdx.normIdx >= 0)
            {
                currObjData.hasNormals = true;
            }
        }


        /// <summary>
        /// Print a summary of the stored data
        /// </summary>
        public void PrintSummary()
        {
            string stats = "This data set has " + objectList.Count + " object(s)" +
                "\n  " + vertList.Count + " vertices" +
                "\n  " + uvList.Count + " uvs" +
                "\n  " + normalList.Count + " normals";
            foreach (ObjectData od in objectList)
            {
                stats += "\n  " + od.name + " has " + od.faceGroups.Count + " group(s)";
                foreach (FaceGroupData gd in od.faceGroups)
                {
                    stats += "\n    " + gd.name + " has " + gd.faces.Count + " faces(s)";
                }
            }
            Debug.Log(stats);
        }


        /// <summary>
        /// Indices for each vertex
        /// </summary>
        public struct FaceIndices
        {
            public int vertIdx;
            public int uvIdx;
            public int normIdx;
        }


        /// <summary>
        /// Container class for object data.
        /// </summary>
        public class ObjectData
        {
            public string name;
            public List<FaceGroupData> faceGroups = new List<FaceGroupData>();
            public List<FaceIndices> allFaces = new List<FaceIndices>();
            public bool hasNormals = false;
            public bool hasColors = false;
            public ObjectData()
            {
            }
        }


        /// <summary>
        /// Container class for faces group data.
        /// </summary>
        public class FaceGroupData
        {
            public string name;
            public string materialName;
            public List<FaceIndices> faces;
            public FaceGroupData()
            {
                faces = new List<FaceIndices>();
            }
            public bool IsEmpty { get { return faces.Count == 0; } }
        }

    }
}


================================================
FILE: Assets/AsImpL/Scripts/Dataset/DataSet.cs.meta
================================================
fileFormatVersion: 2
guid: 41cb908b519c6d441a81eccaf9cadb02
timeCreated: 1487838131
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Dataset/IMaterialFactory.cs
================================================
using UnityEngine;

namespace AsImpL
{
    /// <summary>
    /// Interface for classes that create materials.
    /// </summary>
    public interface IMaterialFactory
    {
        Material Create(string shaderName);
    }
}

================================================
FILE: Assets/AsImpL/Scripts/Dataset/IMaterialFactory.cs.meta
================================================
fileFormatVersion: 2
guid: 72c40b3bf79821f18983ae2c8d50c71d
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Dataset/IShaderSelector.cs
================================================
namespace AsImpL
{
    /// <summary>
    /// Interface for classes that select the shader to use based on the material data.
    /// </summary>
    public interface IShaderSelector
    {
        string Select(MaterialData md, bool useUnlit, ModelUtil.MtlBlendMode blendMode);
    }
}

================================================
FILE: Assets/AsImpL/Scripts/Dataset/IShaderSelector.cs.meta
================================================
fileFormatVersion: 2
guid: 6d7bb6a6dd153df4bbe3388fccaa2593
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Dataset/MaterialData.cs
================================================
using UnityEngine;

namespace AsImpL
{
    /// <summary>
    /// Material data
    /// </summary>
    /// <remarks>This should be completed and extended to support more formats.</remarks>
    /// TODO: fields to store more information should be defined.
    /// TODO: texture mapping data should be defined a separare structure and stored here in a list.
    public class MaterialData
    {
        public string materialName;
        public Color ambientColor;
        public Color diffuseColor;
        public Color specularColor;
        public Color emissiveColor;
        public float shininess = 0.0f;
        public float overallAlpha = 1.0f;
        public int illumType = 0;
        public bool hasReflectionTex = false;
        public string diffuseTexPath;
        public Texture2D diffuseTex;
        public string bumpTexPath;
        public Texture2D bumpTex;
        public string specularTexPath;
        public Texture2D specularTex;
        public string opacityTexPath;
        public Texture2D opacityTex;
    }
}


================================================
FILE: Assets/AsImpL/Scripts/Dataset/MaterialData.cs.meta
================================================
fileFormatVersion: 2
guid: dae7bec6fd5a92c42b9c46811163821e
timeCreated: 1487922714
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Dataset/MaterialFactory.cs
================================================
using UnityEngine;

namespace AsImpL
{
    /// <summary>
    /// Implementation of IMaterialFactory that creates a material based on the shader name.
    /// </summary>
    public class MaterialFactory : IMaterialFactory
    {
        /// <inheritdoc/>
        public Material Create(string shaderName)
        {
            return new Material(Shader.Find(shaderName));
        }
    }
}

================================================
FILE: Assets/AsImpL/Scripts/Dataset/MaterialFactory.cs.meta
================================================
fileFormatVersion: 2
guid: 4aabc90e9be8e4b60b751f8f3ffd299c
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Dataset/ModelReferences.cs
================================================
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_2018_1_OR_NEWER
using Unity.Collections; // ReadOnly attribute
#endif

namespace AsImpL
{
    /// <summary>
    /// Component used to keep track of resources used by a loaded model.
    /// When the component is destroyed all the referenced resources are destroyed.
    /// </summary>
    /// <remarks>This component is added by Loader and it should not be removed.</remarks>
    public class ModelReferences : MonoBehaviour
    {
#if UNITY_2018_1_OR_NEWER
        [ReadOnly]
        [SerializeField]
#endif
        private List<Mesh> meshReferences = new List<Mesh>();
#if UNITY_2018_1_OR_NEWER
        [ReadOnly]
        [SerializeField]
#endif
        private List<Material> materialReferences = new List<Material>();
#if UNITY_2018_1_OR_NEWER
        [ReadOnly]
        [SerializeField]
#endif
        private List<Texture2D> textureReferences = new List<Texture2D>();

        /// <summary>
        /// Add a reference to a created mesh.
        /// </summary>
        /// <param name="mesh">created mesh</param>
        /// <returns>The created mesh itself.</returns>
        public Mesh AddMesh(Mesh mesh)
        {
            meshReferences.Add(mesh);
            return mesh;
        }

        /// <summary>
        /// Add a reference to a created material.
        /// </summary>
        /// <param name="material">created material</param>
        /// <returns>The created material itself.</returns>
        public Material AddMaterial(Material material)
        {
            materialReferences.Add(material);
            return material;
        }

        /// <summary>
        /// Add a reference to a created texture.
        /// </summary>
        /// <param name="texture">created texture</param>
        /// <returns>The created texture itself.</returns>
        public Texture2D AddTexture(Texture2D texture)
        {
            textureReferences.Add(texture);
            return texture;
        }


        /// <summary>
        /// Destroy all the referenced resources when the component is destroyed.
        /// </summary>
        private void OnDestroy()
        {
            int numResources = textureReferences.Count + materialReferences.Count + meshReferences.Count;
            foreach (Texture2D texture in textureReferences)
            {
                Destroy(texture);
            }
            foreach (Material material in materialReferences)
            {
                Destroy(material);
            }
            foreach (Mesh mesh in meshReferences)
            {
                Destroy(mesh);
            }
            Debug.LogFormat("{0} resources destroyed for object {1}", numResources, gameObject.name);
        }

    }
}


================================================
FILE: Assets/AsImpL/Scripts/Dataset/ModelReferences.cs.meta
================================================
fileFormatVersion: 2
guid: 6c1f8e4b5a810a7429623b3c0afbdbbc
timeCreated: 1645617895
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Dataset/ModelUtil.cs
================================================
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace AsImpL
{
    /// <summary>
    /// Utility class for model import
    /// </summary>
    public class ModelUtil
    {
        /// <summary>
        /// Blend mode for Unity Material
        /// </summary>
        public enum MtlBlendMode { OPAQUE, CUTOUT, FADE, TRANSPARENT }


        /// <summary>
        /// Set up a Material for the given mode.
        /// </summary>
        /// <remarks>Here is replicated what is done when choosing a blend mode from Inspector.</remarks>
        /// <param name="mtl">material to be changed</param>
        /// <param name="mode">mode to be set</param>
        public static void SetupMaterialWithBlendMode(Material mtl, MtlBlendMode mode)
        {
            switch (mode)
            {
                case MtlBlendMode.OPAQUE:
                    mtl.SetOverrideTag("RenderType", "Opaque");
                    mtl.SetFloat("_Mode", 0);
                    mtl.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                    mtl.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                    mtl.SetInt("_ZWrite", 1);
                    mtl.DisableKeyword("_ALPHATEST_ON");
                    mtl.DisableKeyword("_ALPHABLEND_ON");
                    mtl.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                    mtl.renderQueue = -1;
                    break;
                case MtlBlendMode.CUTOUT:
                    mtl.SetOverrideTag("RenderType", "TransparentCutout");
                    mtl.SetFloat("_Mode", 1);
                    mtl.SetFloat("_Mode", 1);
                    mtl.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                    mtl.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                    mtl.SetInt("_ZWrite", 1);
                    mtl.EnableKeyword("_ALPHATEST_ON");
                    mtl.DisableKeyword("_ALPHABLEND_ON");
                    mtl.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                    mtl.renderQueue = 2450;
                    break;
                case MtlBlendMode.FADE:
                    mtl.SetOverrideTag("RenderType", "Transparent");
                    mtl.SetFloat("_Mode", 2);
                    mtl.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
                    mtl.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                    mtl.SetInt("_ZWrite", 0);
                    mtl.DisableKeyword("_ALPHATEST_ON");
                    mtl.EnableKeyword("_ALPHABLEND_ON");
                    mtl.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                    mtl.renderQueue = 3000;
                    break;
                case MtlBlendMode.TRANSPARENT:
                    mtl.SetOverrideTag("RenderType", "Transparent");
                    mtl.SetFloat("_Mode", 3);
                    mtl.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                    mtl.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                    mtl.SetInt("_ZWrite", 0);
                    mtl.DisableKeyword("_ALPHATEST_ON");
                    mtl.DisableKeyword("_ALPHABLEND_ON");
                    mtl.EnableKeyword("_ALPHAPREMULTIPLY_ON");
                    mtl.renderQueue = 3000;
                    break;
            }
        }


        /// <summary>
        /// Scan a texture looking for transparent pixels and trying to guess the correct blend mode needed.
        /// </summary>
        /// <param name="texture">input texture (it must be set to readable)</param>
        /// <param name="mode">blend mode set to FADE or CUTOUT if transparent pixels are found.</param>
        /// <returns>Return true if transparent pixels were found.</returns>
        public static bool ScanTransparentPixels(Texture2D texture, ref MtlBlendMode mode)
        {
            bool texCanBeTransparent = texture != null
                && (texture.format == TextureFormat.ARGB32
                || texture.format == TextureFormat.RGBA32
                || texture.format == TextureFormat.DXT5
                || texture.format == TextureFormat.ARGB4444
                || texture.format == TextureFormat.BGRA32
                // Only for DirectX support
#if UNITY_STANDALONE_WIN
                || texture.format == TextureFormat.DXT5Crunched
#endif
                //|| texture.format == ... (all alpha formats)
                );
            if (texCanBeTransparent)
            {
                bool stop = false;
                int pixelScanFrequency = 1;
                for (int x = 0; x < texture.width && !stop; x += pixelScanFrequency)
                {
                    for (int y = 0; y < texture.height && !stop; y += pixelScanFrequency)
                    {
                        float a = texture.GetPixel(x, y).a;
                        DetectMtlBlendFadeOrCutout(a, ref mode, ref stop);
                        if (stop)
                        {
                            return mode == MtlBlendMode.FADE || mode == MtlBlendMode.CUTOUT;
                        }
                    }
                }
            }
            return mode == MtlBlendMode.FADE || mode == MtlBlendMode.CUTOUT;

        }


        /// <summary>
        /// Detect if the blend mode must be set to FADE or CUTOUT
        /// according to the given alpha value and the current value of mode.
        /// </summary>
        /// <param name="alpha">input alpha value</param>
        /// <param name="mode">blend mode set to FADE or CUTOUT</param>
        /// <param name="noDoubt">flag set to true if the mode is finally detected (it can be used to break from a scan loop)</param>
        public static void DetectMtlBlendFadeOrCutout(float alpha, ref MtlBlendMode mode, ref bool noDoubt)
        {
            if (noDoubt)
            {
                return;
            }
            if (alpha < 1.0f)
            {
                //mode = MtlBlendMode.TRANSPARENT;
                if (alpha == 0.0f)
                {
                    // assume there is a "cutout texture"
                    mode = MtlBlendMode.CUTOUT;
                } // else 0<alpha<1
                else if (mode != MtlBlendMode.FADE)
                {
                    // assume there is a "fade texture"
                    mode = MtlBlendMode.FADE;
                    noDoubt = true;
                }
            }
        }


        /// <summary>
        /// Convert a bump map to a normal map
        /// </summary>
        /// <param name="bumpMap">input bump map</param>
        /// <param name="amount">optionally adjust the bump effect with the normal map</param>
        /// <returns>The new normal map</returns>
        public static Texture2D HeightToNormalMap(Texture2D bumpMap, float amount = 1f)
        {
            int h = bumpMap.height;
            int w = bumpMap.width;
            float changeNeg, changePos;
            float /*h0,*/ h1, h2, h3/*, h4*/;
            Texture2D normalMap = new Texture2D(w, h, TextureFormat.ARGB32, true);

            Color col = Color.black;

            for (int y = 0; y < bumpMap.height; y++)
            {
                for (int x = 0; x < bumpMap.width; x++)
                {
                    Vector3 n = Vector3.zero;
                    // CHANGE IN X

                    //h0 = height_map.GetPixel( WrapInt(x-2, w),y).grayscale;
                    h1 = bumpMap.GetPixel(WrapInt(x - 1, w), y).grayscale;
                    h2 = bumpMap.GetPixel(x, y).grayscale;
                    h3 = bumpMap.GetPixel(WrapInt(x + 1, w), y).grayscale;
                    //h4 = height_map.GetPixel(WrapInt(x+2, w) , y).grayscale;

                    //changeNeg = 0.7f*(h1 - h0)+0.2f*(h2 - h1);
                    //changePos = 0.2f*(h3 - h2)+0.7f*(h4 - h3);

                    changeNeg = h2 - h1;
                    changePos = h3 - h2;

                    n.x = -(changePos + changeNeg) / 255.0f;

                    // CHANGE IN Y

                    //h0 = height_map.GetPixel(x, WrapInt(y-2, h)).grayscale;
                    h1 = bumpMap.GetPixel(x, WrapInt(y - 1, h)).grayscale;
                    h2 = bumpMap.GetPixel(x, y).grayscale;
                    h3 = bumpMap.GetPixel(x, WrapInt(y + 1, h)).grayscale;
                    //h4 = height_map.GetPixel(x, WrapInt(y+2, h).grayscale);

                    //changeNeg = 0.7f*(h1 - h0)+0.2f*(h2 - h1);
                    //changePos = 0.2f*(h3 - h2)+0.7f*(h4 - h3);

                    changeNeg = h2 - h1;
                    changePos = h3 - h2;

                    n.y = -(changePos + changeNeg);

                    // SCALE OF BUMPINESS

                    if (amount != 1.0f) n *= amount;

                    /// Get depth component
                    n.z = Mathf.Sqrt(1.0f - (n.x * n.x + n.y * n.y));

                    // Scale in (0..0.5);
                    n *= 0.5f;

                    // set the pixel

                    col.r = Mathf.Clamp01(n.x + 0.5f);
                    col.g = Mathf.Clamp01(n.y + 0.5f);
                    col.b = Mathf.Clamp01(n.z + 0.5f);

                    col.a = col.r;
                    normalMap.SetPixel(x, y, col);
                }
            }

            normalMap.Apply();

            return normalMap;
        }


        /// <summary>
        /// Update a renderer after materials are changed.
        /// </summary>
        /// <param name="renderer">Renderer to be updated.</param>
        public static void UpdateRendererMaterials(Renderer renderer)
		{
#if UNITY_5_6_OR_NEWER
                RendererExtensions.UpdateGIMaterials(renderer);
#else
                DynamicGI.UpdateMaterials(renderer);
#endif
		}


        /// <summary>
        /// Wrap the given value pos inside the range (0..boundary).
        /// </summary>
        /// <param name="pos">input value</param>
        /// <param name="boundary">range boundary</param>
        /// <returns>the wrapped value</returns>
        private static int WrapInt(int pos, int boundary)
        {
            if (pos < 0)
                pos = boundary + pos;
            else if (pos >= boundary)
                pos -= boundary;

            return pos;
        }
    }
}


================================================
FILE: Assets/AsImpL/Scripts/Dataset/ModelUtil.cs.meta
================================================
fileFormatVersion: 2
guid: d645847b11a55f649ac02376e498bc4a
timeCreated: 1488373594
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Dataset/ObjectBuilder.cs
================================================
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

namespace AsImpL
{
    /// <summary>
    /// Build the game object hierarchy with meshes and materials from a DataSet and a MaterialData list.
    /// </summary>
    public class ObjectBuilder
    {
        /// <summary>
        /// Optional build options
        /// </summary>
        public ImportOptions buildOptions = null;
#if UNITY_EDITOR
        /// <summary>
        /// Alternative texture path used to route loading requests to a proper asset database folder.
        /// Set by <see cref="ObjectImporter"/>.
        /// </summary>
        public string alternativeTexPath = null;
#endif
        private BuildStatus buildStatus = new BuildStatus();
        private DataSet currDataSet;
        private GameObject currParentObj;
        private Dictionary<string, Material> currMaterials;
        private List<MaterialData> materialData;

        /// <summary>
        /// Get the indexed list of imported materials
        /// </summary>
        public Dictionary<string, Material> ImportedMaterials { get { return currMaterials; } }

        /// <summary>
        /// Get the number of imported materials or 0 if nothing has been imported.
        /// </summary>
        public int NumImportedMaterials { get { return currMaterials != null ? currMaterials.Count : 0; } }

        /// <summary>
        /// Check if large meshes (32 bit indices) are supported by the current configuration.
        /// </summary>
        public bool LargeMeshesSupported
        {
            get
            {
#if UNITY_2017_3_OR_NEWER
                // GPU support for 32 bit indices is not guaranteed on all platforms;
                // for example Android devices with Mali-400 GPU do not support them.
                // This check is performed in Using32bitIndices().
                // If nothing is rendered on your device probably Using32bitIndices() must be updated.
                if (Using32bitIndices())
                {
                    return true;
                }
#endif
                return false;
            }
        }

        private static int MAX_VERTICES_LIMIT_FOR_A_MESH = 65000;
        private static int MAX_INDICES_LIMIT_FOR_A_MESH = 65000;
        // maximum number of vertices that can be used for triangles
        private static int MAX_VERT_COUNT = (MAX_VERTICES_LIMIT_FOR_A_MESH - 2) / 3 * 3;

        private IShaderSelector _shaderSelector;
        public IShaderSelector ShaderSelector
        {
            get { return _shaderSelector ?? (_shaderSelector = new ShaderSelector()); }
            set { _shaderSelector = value; }
        }

        private IMaterialFactory _materialFactory;
        public IMaterialFactory MaterialFactory
        {
            get { return _materialFactory ?? (_materialFactory = new MaterialFactory()); }
            set { _materialFactory = value; }
        }

        private bool DoubleSidedEnabled
        {
            get { return buildOptions != null && buildOptions.convertToDoubleSided; }
        }


        /// <summary>
        /// Initialize the importing of materials
        /// </summary>
        /// <param name="materialData">List of material data</param>
        /// <param name="hasColors">If true and materialData is null and vertex colors are available, then use them</param>
        public void InitBuildMaterials(List<MaterialData> materialData, bool hasColors, ModelReferences modelRefs)
        {
            this.materialData = materialData;
            currMaterials = new Dictionary<string, Material>();
            if (materialData == null || materialData.Count == 0)
            {
                string shaderName = "VertexLit";
                if (hasColors)
                {
                    shaderName = "Unlit/Simple Vertex Colors Shader";
                    if (Shader.Find(shaderName) == null)
                    {
                        shaderName = "Mobile/Particles/Alpha Blended";
                    }
                    Debug.Log("No material library defined. Using vertex colors.");
                }
                else
                {
                    Debug.LogWarning("No material library defined. Using a default material.");
                }
                Material newMaterial = MaterialFactory.Create(shaderName);
                modelRefs.AddMaterial(newMaterial);
                currMaterials.Add("default", newMaterial);
            }
        }


        /// <summary>
        /// Import materials step by step. Call this until it returns false.
        /// </summary>
        /// <param name="info">Progress information to be updated</param>
        /// <returns>Return true if in progress, false otherwise.</returns>
        public bool BuildMaterials(ProgressInfo info, ModelReferences modelRefs)
        {
            if (materialData == null)
            {
                Debug.LogWarning("No material library defined.");
                return false;
            }
            if (info.materialsLoaded >= materialData.Count)
            {
                return false;
            }
            MaterialData matData = materialData[info.materialsLoaded];
            info.materialsLoaded++;
            if (currMaterials.ContainsKey(matData.materialName))
            {
                Debug.LogWarning("Duplicate material found: " + matData.materialName + ". Repeated occurrence ignored");
            }
            else
            {
                currMaterials.Add(matData.materialName, BuildMaterial(matData, modelRefs));
            }
            return info.materialsLoaded < materialData.Count;
        }


        /// <summary>
        /// Initialize the asynchronous objects building.
        /// Call this once before calling StartBuildObjectAsync().
        /// </summary>
        /// <param name="dataSet">data set used to build the object</param>
        /// <param name="parentObj">game object to which the object will be attached</param>
        /// <param name="materials">dictionary mapping from material name to material</param>
        public void StartBuildObjectAsync(DataSet dataSet, GameObject parentObj, Dictionary<string, Material> materials = null)
        {
            currDataSet = dataSet;
            currParentObj = parentObj;
            if (materials != null)
            {
                currMaterials = materials;
            }
        }


        /// <summary>
        /// Build an object in more steps, one game object at a time.
        /// Call StartBuildObjectAsync() once, then call this until it returns true.
        /// </summary>
        /// <param name="info">progress information data updated on each call</param>
        /// <returns></returns>
        public bool BuildObjectAsync(ref ProgressInfo info)
        {
            bool result = BuildNextObject(currParentObj, currMaterials);
            info.objectsLoaded = buildStatus.objCount;
            info.groupsLoaded = buildStatus.subObjCount;
            info.numGroups = buildStatus.numGroups;
            return result;
        }


        /// <summary>
        /// Calculate tangent space vectors for a mesh.
        /// <see cref="http://forum.unity3d.com/threads/how-to-calculate-mesh-tangents.38984/"/>
        /// </summary>
        /// <param name="origMesh">Mesh to be filled with tangents</param>
        /// TODO: move this to a general utility class?
        public static void Solve(Mesh origMesh)
        {
            if (origMesh.uv == null || origMesh.uv.Length == 0)
            {
                Debug.LogWarning("Unable to compute tangent space vectors - texture coordinates not defined.");
                return;
            }
            if (origMesh.vertices == null || origMesh.vertices.Length == 0)
            {
                Debug.LogWarning("Unable to compute tangent space vectors - vertices not defined.");
                return;
            }
            if (origMesh.normals == null || origMesh.normals.Length == 0)
            {
                Debug.LogWarning("Unable to compute tangent space vectors - normals not defined.");
                return;
            }
            if (origMesh.triangles == null || origMesh.triangles.Length == 0)
            {
                Debug.LogWarning("Unable to compute tangent space vectors - triangles not defined.");
                return;
            }
            Vector3[] vertices = origMesh.vertices;
            Vector3[] normals = origMesh.normals;
            Vector2[] texcoords = origMesh.uv;
            int[] triangles = origMesh.triangles;
            int triVertCount = origMesh.triangles.Length;
            int maxVertIdx = -1;
            for (int i = 0; i < triangles.Length; i++)
            {
                if (maxVertIdx < triangles[i])
                {
                    maxVertIdx = triangles[i];
                }
            }
            if (vertices.Length <= maxVertIdx)
            {
                Debug.LogWarning("Unable to compute tangent space vectors - not enough vertices: " + vertices.Length.ToString());
                return;
            }
            if (normals.Length <= maxVertIdx)
            {
                Debug.LogWarning("Unable to compute tangent space vectors - not enough normals.");
                return;
            }
            if (texcoords.Length <= maxVertIdx)
            {
                Debug.LogWarning("Unable to compute tangent space vectors - not enough UVs.");
                return;
            }

            int vertexCount = origMesh.vertexCount;
            Vector4[] tangents = new Vector4[vertexCount];
            Vector3[] tan1 = new Vector3[vertexCount];
            Vector3[] tan2 = new Vector3[vertexCount];

            int triangleCount = triangles.Length / 3;
            int tri = 0;

            for (int i = 0; i < triangleCount; i++)
            {
                int i1 = triangles[tri];
                int i2 = triangles[tri + 1];
                int i3 = triangles[tri + 2];

                Vector3 v1 = vertices[i1];
                Vector3 v2 = vertices[i2];
                Vector3 v3 = vertices[i3];

                Vector2 w1 = texcoords[i1];
                Vector2 w2 = texcoords[i2];
                Vector2 w3 = texcoords[i3];

                float x1 = v2.x - v1.x;
                float x2 = v3.x - v1.x;
                float y1 = v2.y - v1.y;
                float y2 = v3.y - v1.y;
                float z1 = v2.z - v1.z;
                float z2 = v3.z - v1.z;

                float s1 = w2.x - w1.x;
                float s2 = w3.x - w1.x;
                float t1 = w2.y - w1.y;
                float t2 = w3.y - w1.y;

                float r = 1.0f / (s1 * t2 - s2 * t1);
                Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
                Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);

                tan1[i1] += sdir;
                tan1[i2] += sdir;
                tan1[i3] += sdir;

                tan2[i1] += tdir;
                tan2[i2] += tdir;
                tan2[i3] += tdir;

                tri += 3;
            }

            for (int i = 0; i < vertexCount; i++)
            {
                Vector3 n = normals[i];
                Vector3 t = tan1[i];

                // Gram-Schmidt orthogonalize
                Vector3.OrthoNormalize(ref n, ref t);

                tangents[i].x = t.x;
                tangents[i].y = t.y;
                tangents[i].z = t.z;

                // Calculate handedness
                tangents[i].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[i]) < 0.0f) ? -1.0f : 1.0f;
            }

            origMesh.tangents = tangents;
        }


        /// <summary>
        /// Build mesh colliders for objects with a mesh filter.
        /// </summary>
        /// <param name="targetObject">Game object to process (if it hasn't a mesh filter nothing happens)</param>
        /// <param name="convex">Build a convex mesh collider.</param>
        /// <param name="isTrigger">Set collider as "trigger"</param>
        /// <param name="inflateMesh">Inflate the convex mesh</param>
        /// <param name="skinWidth">Amount to be inflated</param>
        public static void BuildMeshCollider(GameObject targetObject, bool convex = false, bool isTrigger = false, bool inflateMesh = false, float skinWidth = 0.01f)
        {
            MeshFilter meshFilter = targetObject.GetComponent<MeshFilter>();
            if (meshFilter != null && meshFilter.sharedMesh != null)
            {
                Mesh objectMesh = meshFilter.sharedMesh;
                MeshCollider meshCollider = targetObject.AddComponent<MeshCollider>();

                // Note: the order of these assignments is important
                meshCollider.sharedMesh = objectMesh;
                if (convex)
                {
#if !UNITY_2018_3_OR_NEWER
                    meshCollider.skinWidth = skinWidth;
                    meshCollider.inflateMesh = inflateMesh;
#endif
                    meshCollider.convex = convex;
                    meshCollider.isTrigger = isTrigger;
                }
            }
        }


        /// <summary>
        /// Check if the given object data must be split into sub-objects.
        /// </summary>
        /// <param name="objData">object data to be checked</param>
        /// <returns>true only if the given object data must be split.</returns>
        protected bool MeshSplitNeeded(DataSet.ObjectData objData)
        {
            if (LargeMeshesSupported)
            {
                return false;
            }
            if (currDataSet.vertList.Count > MAX_VERTICES_LIMIT_FOR_A_MESH)
            {
                return true;
            }

            int maxIdx4mesh = DoubleSidedEnabled ? MAX_INDICES_LIMIT_FOR_A_MESH / 2 : MAX_INDICES_LIMIT_FOR_A_MESH;
            DataSet.FaceGroupData faceGroup = objData.faceGroups[buildStatus.grpIdx];
            if (faceGroup.faces.Count > maxIdx4mesh)
            {
                return true;
            }

            return false;
        }


        /// <summary>
        /// Build an object once at a time, to be reiterated until false is returned.
        /// </summary>
        /// <param name="parentObj">Game object to which the new objects will be attached</param>
        /// <param name="mats">Materials from the previously loaded library</param>
        /// <returns>Return true until no more objects can be added, then false.</returns>
        protected bool BuildNextObject(GameObject parentObj, Dictionary<string, Material> mats)
        {
            // if all the objects were built stop here
            if (buildStatus.objCount >= currDataSet.objectList.Count)
            {
                return false;
            }

            // get the next object in the list
            DataSet.ObjectData objData = currDataSet.objectList[buildStatus.objCount];

            if (buildStatus.newObject)
            {
                SetUpNewObject(parentObj, objData);
            }

            if ((buildOptions != null && buildOptions.splitByMaterial) || MeshSplitNeeded(objData))
            {
                BuildCurrentPart(objData, mats);
            }
            else
            {
                BuildCurrentMesh(objData, mats);
            }

            buildStatus.subObjCount++;

            if (buildStatus.totFaceIdxCount >= objData.allFaces.Count || buildStatus.grpIdx >= objData.faceGroups.Count)
            {
                if (buildStatus.totFaceIdxCount != objData.allFaces.Count)
                {
                    Debug.LogWarningFormat("Imported face indices: {0} of {1}", buildStatus.totFaceIdxCount, objData.allFaces.Count);
                    return false;
                }

                buildStatus.objCount++;
                buildStatus.newObject = true;
            }

            return true;
        }

        /// <summary>
        /// Set up an object to be built.
        /// </summary>
        /// <param name="parentObj">The "container" object for this object (a mesh can be also directly added to it).</param>
        /// <param name="objData">object data</param>
        protected void SetUpNewObject(GameObject parentObj, DataSet.ObjectData objData)
        {
            if (buildStatus.objCount == 0 && objData.name == "default")
            {
                buildStatus.currObjGameObject = parentObj;
            }
            else
            {
                buildStatus.currObjGameObject = new GameObject();
                buildStatus.currObjGameObject.transform.parent = parentObj.transform;
                buildStatus.currObjGameObject.name = objData.name;
                // restore the scale if the parent was rescaled
                buildStatus.currObjGameObject.transform.localScale = Vector3.one;
            }
            buildStatus.subObjParent = buildStatus.currObjGameObject;

            buildStatus.newObject = false;
            buildStatus.subObjCount = 0;
            buildStatus.idxCount = 0;
            buildStatus.grpIdx = 0;
            buildStatus.grpFaceIdx = 0;
            buildStatus.meshPartIdx = 0;
            buildStatus.totFaceIdxCount = 0;
            buildStatus.numGroups = Mathf.Max(1, objData.faceGroups.Count);
        }


        /// <summary>
        /// Build the current part (called if the splitByMaterial option is set).
        /// </summary>
        /// <param name="objData">Object data.</param>
        /// <param name="matLib">Material library.</param>
        protected void BuildCurrentPart(DataSet.ObjectData objData, Dictionary<string, Material> matLib)
        {
            bool splitLargeMeshes = !LargeMeshesSupported;

            bool splitGrp = false;

            DataSet.FaceGroupData faceGroup = objData.faceGroups[buildStatus.grpIdx];

            DataSet.FaceGroupData grp = new DataSet.FaceGroupData();
            grp.name = faceGroup.name;
            grp.materialName = faceGroup.materialName;


            // data for sub-object
            DataSet.ObjectData subObjData = new DataSet.ObjectData();
            subObjData.hasNormals = objData.hasNormals;
            subObjData.hasColors = objData.hasColors;

            HashSet<int> vertIdxSet = new HashSet<int>();

            bool conv2sided = buildOptions != null && buildOptions.convertToDoubleSided;

            int maxIdx4mesh = conv2sided ? MAX_INDICES_LIMIT_FOR_A_MESH / 2 : MAX_INDICES_LIMIT_FOR_A_MESH;

            // copy blocks of face indices to each sub-object data
            for (int f = buildStatus.grpFaceIdx; f < faceGroup.faces.Count; f++)
            {
                // if large meshed must be split and
                // if passed the max number of vertices and not at the last iteration
                if (splitLargeMeshes && (vertIdxSet.Count / 3 > MAX_VERT_COUNT / 3 || subObjData.allFaces.Count / 3 > maxIdx4mesh / 3))
                {
                    // split the group across more objects
                    splitGrp = true;
                    buildStatus.grpFaceIdx = f;
                    Debug.LogWarningFormat("Maximum vertex number for a mesh exceeded.\nSplitting object {0} (group {1}, starting from index {2})...", grp.name, buildStatus.grpIdx, f);
                    break;
                }
                DataSet.FaceIndices fi = faceGroup.faces[f];
                subObjData.allFaces.Add(fi);
                grp.faces.Add(fi);
                vertIdxSet.Add(fi.vertIdx);
            }

            if (splitGrp || buildStatus.meshPartIdx > 0)
            {
                buildStatus.meshPartIdx++;
            }

            // create an empty (group) object in case the group has been split
            if (buildStatus.meshPartIdx == 1)
            {
                GameObject grpObj = new GameObject();
                grpObj.transform.SetParent(buildStatus.currObjGameObject.transform, false);
                grpObj.name = grp.name;
                buildStatus.subObjParent = grpObj;
            }

            // add a suffix to the group name in case the group has been split
            if (buildStatus.meshPartIdx > 0)
            {
                grp.name = buildStatus.subObjParent.name + "_MeshPart" + buildStatus.meshPartIdx;
            }
            subObjData.name = grp.name;

            // add the group to the sub object data
            subObjData.faceGroups.Add(grp);

            // update the start index
            buildStatus.idxCount += subObjData.allFaces.Count;

            if (!splitGrp)
            {
                buildStatus.grpFaceIdx = 0;
                buildStatus.grpIdx++;
            }
            buildStatus.totFaceIdxCount += subObjData.allFaces.Count;

            GameObject subobj = ImportSubObject(buildStatus.subObjParent, subObjData, matLib);
            if (subobj == null)
            {
                Debug.LogWarningFormat("Error loading sub object n.{0}.", buildStatus.subObjCount);
            }
            //else Debug.LogFormat( "Imported face indices: {0} to {1}", buildStatus.totFaceIdxCount - sub_od.AllFaces.Count, buildStatus.totFaceIdxCount );
        }


        /// <summary>
        /// Build a sub-object of the current part (called if the splitByMaterial option is set).
        /// </summary>
        /// <param name="parentObj"></param>
        /// <param name="objData">Object data.</param>
        /// <param name="matLib">Material library.</param>
        /// <returns>The GameObject created for the sub object.</returns>
        protected GameObject ImportSubObject(GameObject parentObj, DataSet.ObjectData objData, Dictionary<string, Material> matLib)
        {
            GameObject go = new GameObject();
            go.name = objData.name;
			
			// make the object name unique, adding a progressive number if needed
            int count = 0;
            if (parentObj.transform)
            {
                while (parentObj.transform.Find(go.name))
                {
                    count++;
                    go.name = objData.name + count;
                }
            }
            go.transform.SetParent(parentObj.transform, false);

            if (objData.allFaces.Count == 0)
            {
                Debug.LogWarning("Sub object: " + objData.name + " has no face defined. Creating empty game object.");

                return go;
            }

            //Debug.Log( "Importing sub object:" + objData.Name );


            go.AddComponent<MeshFilter>();
            go.AddComponent<MeshRenderer>();

            Renderer renderer = go.GetComponent<Renderer>();

            Mesh mesh = BuildMesh(renderer, objData, matLib);
			
			FinalizeObject(go,mesh);

            return go;
        }


        /// <summary>
        /// Build the mesh for the current object (called if the splitByMaterial option is NOT set).
        /// </summary>
        /// <param name="objData">Object data.</param>
        /// <param name="matLib">Material library.</param>
        protected void BuildCurrentMesh(DataSet.ObjectData objData, Dictionary<string, Material> matLib)
        {
            if (objData.allFaces.Count == 0)
            {
                Debug.LogWarning("Object: " + objData.name + " has no face defined.");
                return;
            }
            DataSet.FaceGroupData faceGroup = objData.faceGroups[buildStatus.grpIdx];
            GameObject go = buildStatus.currObjGameObject;
            go.AddComponent<MeshFilter>();
            go.AddComponent<MeshRenderer>();

            Dictionary<string, int> vIdxCount;
            Mesh mesh = CreateMesh(objData, out vIdxCount);
            mesh.subMeshCount = objData.faceGroups.Count;

            Material[] faceMaterials = new Material[objData.faceGroups.Count];
            for (int i = 0; i < objData.faceGroups.Count; i++)
            {
                Material material = GetLibraryMaterial(matLib, objData.faceGroups[i].materialName);

                faceMaterials[i] = material;

                int numIndices = BuildSubMesh(mesh, objData, vIdxCount, i);

                buildStatus.grpFaceIdx = 0;
                buildStatus.grpIdx++;
                buildStatus.totFaceIdxCount += numIndices;
            }

            Renderer renderer = go.GetComponent<Renderer>();

            renderer.materials = faceMaterials;
            ModelUtil.UpdateRendererMaterials(renderer);

            FinalizeMesh(mesh, objData.hasNormals);

			FinalizeObject(go, mesh);
            // update the start index
            //buildStatus.idxCount += objData.faceGroups.Count;

        }


        /// <summary>
        /// Build and set up a mesh (always called when building an object).
        /// </summary>
        /// <param name="renderer">Renderer where mesh materials are added.</param>
        /// <param name="objData">Object data.</param>
        /// <param name="matLib">Material library.</param>
        /// <returns>A new mesh, its materials are added to the given renderer.</returns>
        protected Mesh BuildMesh(Renderer renderer, DataSet.ObjectData objData, Dictionary<string, Material> matLib)
        {
            Dictionary<string, int> vIdxCount;
            Mesh mesh = CreateMesh(objData, out vIdxCount);

            Material material = GetLibraryMaterial(matLib, objData.faceGroups[0].materialName);

            if (material != null)
            {
                renderer.sharedMaterial = material;
                ModelUtil.UpdateRendererMaterials(renderer);
            }

            BuildSubMesh(mesh, objData, vIdxCount, 0);

            FinalizeMesh(mesh, objData.hasNormals);

            return mesh;
        }


        /// <summary>
        /// Create a mesh with only vertices information defined.
        /// </summary>
        /// <param name="objData">Object data.</param>
        /// <param name="vIdxCount">Counter for vertex info (position, UV, normal) to be shared among faces.</param>
        /// <returns>The created mesh with only vertices information defined.</returns>
        protected Mesh CreateMesh(DataSet.ObjectData objData, out Dictionary<string, int> vIdxCount)
        {
            bool conv2sided = DoubleSidedEnabled;

            // count vertices needed for all the faces and map face indices to new vertices
            vIdxCount = new Dictionary<string, int>();
            foreach (DataSet.FaceIndices fi in objData.allFaces)
            {
                string key = DataSet.GetFaceIndicesKey(fi);
                int idx;
                // avoid duplicates
                if (!vIdxCount.TryGetValue(key, out idx))
                {
                    vIdxCount.Add(key, vIdxCount.Count);
                }
            }
            int vcount = vIdxCount.Count;

            int arraySize = conv2sided ? vcount * 2 : vcount;

            Vector3[] newVertices = new Vector3[arraySize];
            Vector2[] newUVs = new Vector2[arraySize];
            Vector3[] newNormals = new Vector3[arraySize];
            Color32[] newColors = new Color32[arraySize];

            bool hasColors = currDataSet.colorList.Count > 0;

            foreach (DataSet.FaceIndices fi in objData.allFaces)
            {
                string key = DataSet.GetFaceIndicesKey(fi);
                int k = vIdxCount[key];
                newVertices[k] = currDataSet.vertList[fi.vertIdx];
                if (conv2sided)
                {
                    newVertices[vcount + k] = newVertices[k];
                }
                if (hasColors)
                {
                    newColors[k] = currDataSet.colorList[fi.vertIdx];
                    if (conv2sided)
                    {
                        newColors[vcount + k] = newColors[k];
                    }
                }
                if (currDataSet.uvList.Count > 0)
                {
                    newUVs[k] = currDataSet.uvList[fi.uvIdx];
                    if (conv2sided)
                    {
                        newUVs[vcount + k] = newUVs[k];
                    }
                }
                if (currDataSet.normalList.Count > 0 && fi.normIdx >= 0)
                {
                    newNormals[k] = currDataSet.normalList[fi.normIdx];
                    if (conv2sided)
                    {
                        newNormals[vcount + k] = -newNormals[k];
                    }
                }
            }

            Mesh mesh = new Mesh();

#if UNITY_2017_3_OR_NEWER
            // Enable 32 bit indices only if needed
            if (Using32bitIndices())
            {
                int maxIndexCount = 0;
                for (int i = 0; i <objData.faceGroups.Count; i++)
                {
                    if (maxIndexCount < objData.faceGroups[i].faces.Count)
                    {
                        maxIndexCount = objData.faceGroups[i].faces.Count;
                    }
                }
                int numIndices = conv2sided ? maxIndexCount * 2 : maxIndexCount;

                if (arraySize > MAX_VERT_COUNT || numIndices > MAX_INDICES_LIMIT_FOR_A_MESH)
                {
                    mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
                }
            }
#endif

            mesh.vertices = newVertices;
            bool objectHasNormals = (currDataSet.normalList.Count > 0 && objData.hasNormals);
            bool objectHasColors = (currDataSet.colorList.Count > 0 && objData.hasColors);
            bool objectHasUVs = (currDataSet.uvList.Count > 0);

            if (objectHasUVs) mesh.uv = newUVs;
            if (objectHasNormals) mesh.normals = newNormals;
            if (objectHasColors) mesh.colors32 = newColors;

            return mesh;
        }


        /// <summary>
        /// Build the faces for the given (sub)mesh according to the given data.
        /// </summary>
        /// <param name="mesh">The mesh to which the faces will be added.</param>
        /// <param name="objData">Object data.</param>
        /// <param name="vIdxCount">Counter for vertex info (position, UV, normal) to be shared among faces.</param>
        /// <param name="subMeshIndex">Index of the sub-mesh</param>
        /// <returns>The number of indices of the mesh (even in case of double sided option).</returns>
        protected int BuildSubMesh(Mesh mesh, DataSet.ObjectData objData, Dictionary<string, int> vIdxCount, int subMeshIndex)
        {
            int n = objData.faceGroups[subMeshIndex].faces.Count;
            bool conv2sided = DoubleSidedEnabled;
            int numIndices = conv2sided ? n * 2 : n;
            int[] indices = new int[numIndices];

            for (int s = 0; s < n; s++)
            {
                DataSet.FaceIndices fi = objData.faceGroups[subMeshIndex].faces[s];
                string key = DataSet.GetFaceIndicesKey(fi);
                indices[s] = vIdxCount[key];
            }
            if (conv2sided)
            {
                int vcount = vIdxCount.Count;
                for (int s = 0; s < n; s++)
                {
                    indices[s + n] = vcount + indices[s / 3 * 3 + 2 - s % 3];
                }
            }

            mesh.SetTriangles(indices, subMeshIndex);

            return numIndices;
        }


        /// <summary>
        /// Compute missing data for the given mesh.
        /// </summary>
        /// <param name="mesh">Existing mesh to be finalized.</param>
        /// <param name="objDataHasNormals">Flag to inform if nomals data is provided (or if it must be computed).</param>
        protected void FinalizeMesh(Mesh mesh, bool objDataHasNormals)
        {
            bool objectHasNormals = (currDataSet.normalList.Count > 0 && objDataHasNormals);
            bool objectHasUVs = (currDataSet.uvList.Count > 0);
            if (!objectHasNormals)
            {
                mesh.RecalculateNormals();
            }
            if (objectHasUVs)
            {
                Solve(mesh);
            }
       }


        /// <summary>
        /// Finalize the given object adding the given mesh (and updating its collider if needed).
        /// </summary>
        /// <param name="incompleteObj">Object to be completed and finalized.</param>
        /// <param name="mesh">Mesh to be added to the object.</param>
        protected void FinalizeObject(GameObject incompleteObj, Mesh mesh)
		{
            ModelReferences modelRefs = incompleteObj.GetComponentInParent<ModelReferences>();
            modelRefs.AddMesh(mesh);
            mesh.name = incompleteObj.name;
            MeshFilter meshFilter = incompleteObj.GetComponent<MeshFilter>();
            meshFilter.sharedMesh = mesh;

            if (buildOptions != null && buildOptions.buildColliders)
            {
#if UNITY_2018_3_OR_NEWER
                BuildMeshCollider(incompleteObj, buildOptions.colliderConvex, buildOptions.colliderTrigger);
#else
                BuildMeshCollider(incompleteObj, buildOptions.colliderConvex, buildOptions.colliderTrigger, buildOptions.colliderInflate, buildOptions.colliderSkinWidth);
#endif
            }
		}

        /// <summary>
        /// Get a material given its name and library (falling back to a default material if not found).
        /// </summary>
        /// <param name="materialLibrary">The dictionary containing the material library.</param>
        /// <param name="materialName">Name of the material.</param>
        /// <returns>The required material, a default material or null if no material is available.</returns>
        protected Material GetLibraryMaterial(Dictionary<string, Material> materialLibrary, string materialName)
        {
            Material material = null;
            string matName = (materialName != null) ? materialName : "default";

            if (materialLibrary.ContainsKey(matName))
            {
                material = materialLibrary[matName];
            }
            else
            {
                if (materialLibrary.ContainsKey("default"))
                {
                    material = materialLibrary["default"];
                    Debug.LogWarning("Material: " + matName + " not found. Using the default material.");
                }
                else
                {
                    Debug.LogError("Material: " + matName + " not found.");
                }
            }
            return material;
        }


        /// <summary>
        /// Build a Unity Material from MaterialData
        /// </summary>
        /// <param name="mtlData">material data</param>
        /// <returns>Unity material</returns>
        protected Material BuildMaterial(MaterialData mtlData, ModelReferences modelRefs)
        {
            bool specularMode = false;// (md.specularTex != null);
            ModelUtil.MtlBlendMode mode = mtlData.overallAlpha < 1.0f ? ModelUtil.MtlBlendMode.TRANSPARENT : ModelUtil.MtlBlendMode.OPAQUE;

            bool useUnlit = buildOptions != null && buildOptions.litDiffuse
                && mtlData.diffuseTex != null
                && mtlData.bumpTex == null
                && mtlData.opacityTex == null
                && mtlData.specularTex == null
                && !mtlData.hasReflectionTex;

            bool? diffuseIsTransparent = null;
            if (useUnlit)
            {
                // do not use unlit shader if the texture has transparent pixels
                diffuseIsTransparent = ModelUtil.ScanTransparentPixels(mtlData.diffuseTex, ref mode);
            }

            Material newMaterial = MaterialFactory.Create(ShaderSelector.Select(mtlData, useUnlit, mode)); // "Standard (Specular setup)"
            modelRefs.AddMaterial(newMaterial);
            newMaterial.name = mtlData.materialName;

            float shinLog = Mathf.Log(mtlData.shininess, 2);
            // get the metallic value from the shininess
            float metallic = Mathf.Clamp01(shinLog / 10.0f);
            // get the smoothness from the shininess
            float smoothness = Mathf.Clamp01(shinLog / 10.0f);
            if (specularMode)
            {
                newMaterial.SetColor("_SpecColor", mtlData.specularColor);
                newMaterial.SetFloat("_Shininess", mtlData.shininess / 1000.0f);
                //m.color = new Color( md.diffuse.r, md.diffuse.g, md.diffuse.b, md.alpha);
            }
            else
            {
                newMaterial.SetFloat("_Metallic", metallic);
                //m.SetFloat( "_Glossiness", md.shininess );
            }


            if (mtlData.diffuseTex != null)
            {
                // diffuse

                if (mtlData.opacityTex != null)
                {
                    // diffuse + opacity:
                    // update diffuse texture if an opacity map was found
                    int w = mtlData.diffuseTex.width;
                    int h = mtlData.diffuseTex.width;
                    Texture2D albedoTexture = new Texture2D(w, h, TextureFormat.ARGB32, false);
                    modelRefs.AddTexture(albedoTexture);
                    Color col = new Color();
                    for (int x = 0; x < albedoTexture.width; x++)
                    {
                        for (int y = 0; y < albedoTexture.height; y++)
                        {
                            col = mtlData.diffuseTex.GetPixel(x, y);
                            col.a *= mtlData.opacityTex.GetPixel(x, y).grayscale;
                            // blend diffuse and opacity textures
                            albedoTexture.SetPixel(x, y, col);
                        }
                    }
                    albedoTexture.name = mtlData.diffuseTexPath;
                    albedoTexture.Apply();
                    // mode = ModelUtil.MtlBlendMode.TRANSPARENT;
                    // The map_d value is multiplied by the d value --> Fade mode
                    mode = ModelUtil.MtlBlendMode.FADE;
#if UNITY_EDITOR
                    if (!string.IsNullOrEmpty(alternativeTexPath))
                    {
                        string texAssetPath = AssetDatabase.GetAssetPath(mtlData.opacityTex);
                        if (!string.IsNullOrEmpty(texAssetPath))
                        {
                            EditorUtil.SaveAndReimportPngTexture(ref albedoTexture, texAssetPath, "_alpha");
                        }
                    }
#endif
                    newMaterial.SetTexture("_MainTex", albedoTexture);
                }
                else
                {// md.opacityTex == null

                    // diffuse without opacity: if there are transparent pixels ==> transparent material
                    if (!diffuseIsTransparent.HasValue)
                    {
                        diffuseIsTransparent = ModelUtil.ScanTransparentPixels(mtlData.diffuseTex, ref mode);
                    }
                    newMaterial.SetTexture("_MainTex", mtlData.diffuseTex);
                }
                //Debug.LogFormat("Diffuse set for {0}",m.name);
            }
            else if (mtlData.opacityTex != null)
            {
                // opacity without diffuse
                //mode = ModelUtil.MtlBlendMode.TRANSPARENT;
                mode = ModelUtil.MtlBlendMode.FADE;
                int w = mtlData.opacityTex.width;
                int h = mtlData.opacityTex.width;
                Texture2D albedoTexture = new Texture2D(w, h, TextureFormat.ARGB32, false);
                modelRefs.AddTexture(albedoTexture);
                Color col = new Color();
                bool detected = false;
                for (int x = 0; x < albedoTexture.width; x++)
                {
                    for (int y = 0; y < albedoTexture.height; y++)
                    {
                        col = mtlData.diffuseColor;
                        col.a = mtlData.overallAlpha * mtlData.opacityTex.GetPixel(x, y).grayscale;
                        ModelUtil.DetectMtlBlendFadeOrCutout(col.a, ref mode, ref detected);
                        //if (md.alpha == 1.0f && col.a == 0.0f) mode = ModelUtil.MtlBlendMode.CUTOUT;
                        albedoTexture.SetPixel(x, y, col);
                    }
                }
                albedoTexture.name = mtlData.diffuseTexPath;
                albedoTexture.Apply();
#if UNITY_EDITOR
                if (!string.IsNullOrEmpty(alternativeTexPath))
                {
                    string texAssetPath = AssetDatabase.GetAssetPath(mtlData.opacityTex);
                    if (!string.IsNullOrEmpty(texAssetPath))
                    {
                        EditorUtil.SaveAndReimportPngTexture(ref albedoTexture, texAssetPath, "_op");
                    }
                }
#endif
                newMaterial.SetTexture("_MainTex", albedoTexture);
            }

            mtlData.diffuseColor.a = mtlData.overallAlpha;
            newMaterial.SetColor("_Color", mtlData.diffuseColor);

            mtlData.emissiveColor.a = mtlData.overallAlpha;
            newMaterial.SetColor("_EmissionColor", mtlData.emissiveColor);
            if (mtlData.emissiveColor.r > 0 || mtlData.emissiveColor.g > 0 || mtlData.emissiveColor.b > 0)
            {
                newMaterial.EnableKeyword("_EMISSION");
            }

            if (mtlData.bumpTex != null)
            {
                // bump map defined

                // TODO: if importing assets do not create a normal map, change importer settings

                // let (improperly) assign a normal map to the bump map
                // if the file name contains a specific tag
                // TODO: customize normal map tag
                if (mtlData.bumpTexPath.Contains("_normal_map"))
                {
                    newMaterial.EnableKeyword("_NORMALMAP");
                    newMaterial.SetFloat("_BumpScale", 0.25f); // lower the bump effect with the normal map
                    newMaterial.SetTexture("_BumpMap", mtlData.bumpTex);
                }
                else
                {
                    // calculate normal map
                    Texture2D normalMap = ModelUtil.HeightToNormalMap(mtlData.bumpTex);
                    modelRefs.AddTexture(normalMap);
#if UNITY_EDITOR
                    if (!string.IsNullOrEmpty(alternativeTexPath))
                    {
                        string texAssetPath = AssetDatabase.GetAssetPath(mtlData.bumpTex);
                        if (!string.IsNullOrEmpty(texAssetPath))
                        {
                            EditorUtil.SaveAndReimportPngTexture(ref normalMap, texAssetPath, "_nm", true);
                        }
                    }
                    else
#endif
                    {
                        newMaterial.SetTexture("_BumpMap", normalMap);
                        //newMaterial.SetTexture("_BumpMap", md.bumpTex);
                        newMaterial.EnableKeyword("_NORMALMAP");
                        newMaterial.SetFloat("_BumpScale", 1.0f); // adjust the bump effect with the normal map
                    }
                }
            }

            if (mtlData.specularTex != null)
            {
                Texture2D glossTexture = new Texture2D(mtlData.specularTex.width, mtlData.specularTex.height, TextureFormat.ARGB32, false);
                modelRefs.AddTexture(glossTexture);
                Color col = new Color();
                float pix = 0.0f;
                for (int x = 0; x < glossTexture.width; x++)
                {
                    for (int y = 0; y < glossTexture.height; y++)
                    {
                        pix = mtlData.specularTex.GetPixel(x, y).grayscale;

                        // red = metallic

                        col.r = metallic * pix;// md.specular.grayscale*pix;
                        col.g = col.r;
                        col.b = col.r;

                        // alpha = smoothness

                        // if reflecting set maximum smoothness value, else use a precomputed value
                        if (mtlData.hasReflectionTex) col.a = pix;
                        else col.a = pix * smoothness;

                        glossTexture.SetPixel(x, y, col);
                    }
                }
                glossTexture.Apply();
#if UNITY_EDITOR
                if (!string.IsNullOrEmpty(alternativeTexPath))
                {
                    string texAssetPath = AssetDatabase.GetAssetPath(mtlData.specularTex);
                    if (!string.IsNullOrEmpty(texAssetPath))
                    {
                        EditorUtil.SaveAndReimportPngTexture(ref glossTexture, texAssetPath, "_spec");
                    }
                }
#endif

                if (specularMode)
                {
                    newMaterial.EnableKeyword("_SPECGLOSSMAP");
                    newMaterial.SetTexture("_SpecGlossMap", glossTexture);
                }
                else
                {
                    newMaterial.EnableKeyword("_METALLICGLOSSMAP");
                    newMaterial.SetTexture("_MetallicGlossMap", glossTexture);
                }

                //m.SetTexture( "_MetallicGlossMap", md.specularLevelTex );
            }

            // replace the texture with Unity environment reflection
            if (mtlData.hasReflectionTex)
            {
                if (mtlData.overallAlpha < 1.0f)
                {
                    Color col = Color.white;
                    col.a = mtlData.overallAlpha;
                    newMaterial.SetColor("_Color", col);
                    mode = ModelUtil.MtlBlendMode.FADE;
                }
                // the "amount of" info is missing, using a default value
                if (mtlData.specularTex != null)
                {
                    newMaterial.SetFloat("_Metallic", metallic);// 1.0f);
                }
                // usually the reflection texture is not blurred
                newMaterial.SetFloat("_Glossiness", 1.0f);
            }

            ModelUtil.SetupMaterialWithBlendMode(newMaterial, mode);

            //#if UNITY_EDITOR
            //        if (!string.IsNullOrEmpty(alternateTexPath))
            //        {
            //            string path = alternateTexPath + "../Materials/" + m.name + ".mat";
            //            path = path.Replace("Textures/../", "");
            //            Debug.LogFormat("Creating material asset in {0}", path);
            //            AssetDatabase.CreateAsset(m, path);
            //        m = AssetDatabase.LoadAssetAtPath<Material>(path);
            //        }
            //#endif
            return newMaterial;
        }


#if UNITY_2017_3_OR_NEWER
        /// <summary>
        /// Check if the GPU support for 32 bit indices is enabled and available.
        /// </summary>
        /// <remarks>
        /// GPU support for 32 bit indices is not guaranteed on all platforms;
        /// for example Android devices with Mali-400 GPU do not support them.
        /// </remarks>
        /// <returns>True if the GPU support for 32 bit indices is enabled and available.</returns>
        private bool Using32bitIndices()
        {
            if (buildOptions != null && !buildOptions.use32bitIndices)
            {
                // Do not use at all 32 bit indices only if explicitly required.
                return false;
            }
#if UNITY_ANDROID
            string graphicsDeviceName = SystemInfo.graphicsDeviceName;
            // If nothing is rendered on your device probably a new device check must be added here.
            if (graphicsDeviceName.Contains("Mali") && graphicsDeviceName.Contains("400"))
            {
                // Android devices with Mali-400 GPU do not support 32 bit indices
                return false;
            }
#endif
            return true;
        }
#endif


        public class ProgressInfo
        {
            public int materialsLoaded = 0;
            public int objectsLoaded = 0;
            public int groupsLoaded = 0;
            public int numGroups = 0;
        }


        private class BuildStatus
        {
            // true if a new object must be created
            public bool newObject = true;

            // counter for objects
            public int objCount = 0;

            // counter for sub objects
            public int subObjCount = 0;

            // number of added indices
            public int idxCount = 0;

            // index of the last group
            public int grpIdx = 0;

            // number of the groups for the last object
            public int numGroups = 0;

            // index of the first face index in the group
            public int grpFaceIdx = 0;

            // index of the last mesh part if the group is split into parts
            public int meshPartIdx = 0;

            // total number of face indices processed
            public int totFaceIdxCount = 0;

            // current OBJ object
            public GameObject currObjGameObject = null;
            internal GameObject subObjParent;
        }

    }
}


================================================
FILE: Assets/AsImpL/Scripts/Dataset/ObjectBuilder.cs.meta
================================================
fileFormatVersion: 2
guid: 5d3b8da2516ecbd45a3510f7b70c877c
timeCreated: 1487834182
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Dataset/ShaderSelector.cs
================================================
namespace AsImpL
{
    /// <summary>
    /// Default implementation of IShaderSelector using predefined shaders.
    /// </summary>
    public class ShaderSelector : IShaderSelector
    {
        private readonly string defaultShader;

        public ShaderSelector(string defaultShader = "Standard")
        {
            this.defaultShader = defaultShader;
        }

        /// <inheritdoc/>
        public string Select(MaterialData md, bool useUnlit, ModelUtil.MtlBlendMode blendMode)
        {
            //const bool specularMode = false;// (md.specularTex != null);

            bool? diffuseIsTransparent = null;
            if (useUnlit)
            {
                // do not use unlit shader if the texture has transparent pixels
                diffuseIsTransparent = ModelUtil.ScanTransparentPixels(md.diffuseTex, ref blendMode);
            }

            if (useUnlit && !diffuseIsTransparent.Value)
            {
                return "Unlit/Texture";
            }
            //else if (specularMode)
            //{
            //    return "Standard (Specular setup)";
            //}

            return defaultShader; // (md.illumType == 2) ? "Standard (Specular setup)" : defaultShader
        }
    }
}


================================================
FILE: Assets/AsImpL/Scripts/Dataset/ShaderSelector.cs.meta
================================================
fileFormatVersion: 2
guid: 73f70be058a983bdfb31daa3caad5069
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Dataset/Triangulator.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using AsImpL.MathUtil;

namespace AsImpL
{
    /// <summary>
    /// Implements triangulation of a face of a data set.
    /// </summary>
    public static class Triangulator
    {
        /// <summary>
        /// Triangulate a face of the given dataset.
        /// </summary>
        /// <param name="dataSet">Input data set.</param>
        /// <param name="face">Face to be triangulated (with more than 3 vertices)</param>
        public static void Triangulate(DataSet dataSet, DataSet.FaceIndices[] face)
        {
            int numVerts = face.Length;
            //Debug.LogFormat("Triangulating a face with {0} vertices of {1}...", numVerts, dataSet.CurrGroupName);
            Vector3 planeNormal = FindPlaneNormal(dataSet, face);

            // setup the data structure used for triangulation
            List<Vertex> poly = new List<Vertex>();
            for (int i = 0; i < numVerts; i++)
            {
                int idx = face[i].vertIdx;
                poly.Add(new Vertex(i, dataSet.vertList[idx]));
            }

            // use the ear clipping triangulation
            List<Triangle> newTris = Triangulation.TriangulateByEarClipping(poly, planeNormal, dataSet.CurrGroupName);

            // copy the data structure used for triangulation back to the data set
            for (int t = 0; t < newTris.Count; t++)
            {
                int idx1 = newTris[t].v1.OriginalIndex;
                int idx2 = newTris[t].v2.OriginalIndex;
                int idx3 = newTris[t].v3.OriginalIndex;
                dataSet.AddFaceIndices(face[idx1]);
                dataSet.AddFaceIndices(face[idx3]);
                dataSet.AddFaceIndices(face[idx2]);
            }
        }


        /// <summary>
        /// Get a normal of a plane used for polygon projection.
        /// </summary>
        /// <param name="dataSet">Input data set.</param>
        /// <param name="face">Face to be triangulated</param>
        /// <returns>The mean of the normals if available or a vector perpendicular to the first triangle</returns>
        public static Vector3 FindPlaneNormal(DataSet dataSet, DataSet.FaceIndices[] face)
        {
            int vertCount = face.Length;
            bool hasNormals = dataSet.normalList.Count > 0;
            Vector3 planeNormal = Vector3.zero;
            if (hasNormals)
            {
                // if it has normals use the mean of the normals of the vertices
                for (int i = 0; i < vertCount; i++)
                {
                    int normalIdx = face[i].normIdx;
                    planeNormal += dataSet.normalList[normalIdx];
                }
                planeNormal.Normalize();
            }
            else
            {
                // else calculate a vector perpendicular to the first triangle
                Vector3 v0 = dataSet.vertList[face[0].vertIdx];
                Vector3 v1 = dataSet.vertList[face[1].vertIdx];
                Vector3 vn = dataSet.vertList[face[vertCount - 1].vertIdx];
                planeNormal = MathUtility.ComputeNormal(v0, v1, vn);
            }
            return planeNormal;
        }

    }
}


================================================
FILE: Assets/AsImpL/Scripts/Dataset/Triangulator.cs.meta
================================================
fileFormatVersion: 2
guid: 9ade097d341a67c4ab7ace3b1b12badd
timeCreated: 1547202713
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Dataset.meta
================================================
fileFormatVersion: 2
guid: c9c1191ef9829594988154266262f765
folderAsset: yes
timeCreated: 1486633140
licenseType: Free
DefaultImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Editor/ObjImportWindow.cs
================================================
using System.IO;
using UnityEngine;
using UnityEditor;

namespace AsImpL
{
    /// <summary>
    /// Editor window for OBJ importing configuration and control
    /// </summary>
    /// TODO: replace this with a wizard and support more formats
    public class ObjImportWindow : EditorWindow
    {
        private string defaultImportPath = "";
        private string lastPath = string.Empty;
        private float scale = 1f;
        private bool convertUpAxis = false;
        private bool convertToDoubleSided = false;
        private bool litDiffuseMap = false;
        private bool buildColliders = false;
        private bool colliderConvex = false;
        private bool colliderTrigger = false;
#if !UNITY_2018_3_OR_NEWER
        private bool colliderInflate = false;
        public float colliderSkinWidth = 0.01f;
#endif
        private bool importAssets = false;
        private string importAssetPath = "ImportedOBJ";
#if UNITY_2017_3_OR_NEWER
        private bool use32bitIndices = false;
#endif
        private bool hideWhileLoading = false;
        private bool splitByMaterial = false;

        private bool loading = false;
        private GameObject objObject;
        private ObjectImporter objImporter;


        [MenuItem("Assets/Import OBJ model... [AsImpL]", false, 20)]
        private static void ShowWindow()
        {
            GetWindow<ObjImportWindow>(false, "OBJ import", true);
        }


        [MenuItem("Window/Capture screenshot [AsImpL]", false)]
        private static void Screenshot()
        {
            EditorUtil.AutoCaptureScreenshot("AsImpL");
        }


        private void SaveSettings()
        {
            defaultImportPath = defaultImportPath.Replace('\\', '/');
            importAssetPath = importAssetPath.Replace('\\', '/');
            Debug.Log("Default path set to: " + defaultImportPath);
            Debug.Log("Import path set to: " + importAssetPath);
            EditorPrefs.SetString("AsImpL_ImportPath", defaultImportPath);
            EditorPrefs.SetString("AsImpL_LastPath", lastPath);
            EditorPrefs.SetFloat("AsImpL_AssetScale", scale);
            EditorPrefs.SetBool("AsImpL_AssetVertAxis", convertUpAxis);
            EditorPrefs.SetBool("AsImpL_AssetDoubleSided", convertToDoubleSided);
            EditorPrefs.SetBool("AsImpL_DiffuseHasLightMap", litDiffuseMap);
            EditorPrefs.SetBool("AsImpL_BuildColliders", buildColliders);
            EditorPrefs.SetBool("AsImpL_ColliderConvex", colliderConvex);
            EditorPrefs.SetBool("AsImpL_ColliderTrigger", colliderTrigger);
#if !UNITY_2018_3_OR_NEWER
            EditorPrefs.SetBool("AsImpL_ColliderInflate", colliderInflate);
            EditorPrefs.SetFloat("AsImpL_ColliderSkinWidth", colliderSkinWidth);
#endif
            EditorPrefs.SetBool("AsImpL_HideWhileLoading", hideWhileLoading);
            EditorPrefs.SetBool("AsImpL_SplitByMaterial", splitByMaterial);
            EditorPrefs.SetBool("AsImpL_ImportAssets", importAssets);
            EditorPrefs.SetString("AsImpL_AssetPath", importAssetPath);
#if UNITY_2017_3_OR_NEWER
            EditorPrefs.SetBool("AsImpL_Use32bitIndices", use32bitIndices);
#endif
        }


        private void ResetSettings()
        {
            if (EditorPrefs.HasKey("AsImpL_ImportPath"))
            {
                defaultImportPath = EditorPrefs.GetString("AsImpL_ImportPath");
            }
            if (EditorPrefs.HasKey("AsImpL_LastPath"))
            {
                lastPath = EditorPrefs.GetString("AsImpL_LastPath");
            }
            if (EditorPrefs.HasKey("AsImpL_AssetScale"))
            {
                scale = EditorPrefs.GetFloat("AsImpL_AssetScale");
            }
            if (EditorPrefs.HasKey("AsImpL_AssetVertAxis"))
            {
                convertUpAxis = EditorPrefs.GetBool("AsImpL_AssetVertAxis");
            }
            if (EditorPrefs.HasKey("AsImpL_AssetDoubleSided"))
            {
                convertToDoubleSided = EditorPrefs.GetBool("AsImpL_AssetDoubleSided");
            }
            if (EditorPrefs.HasKey("AsImpL_DiffuseHasLightMap"))
            {
                litDiffuseMap = EditorPrefs.GetBool("AsImpL_DiffuseHasLightMap");
            }
            if (EditorPrefs.HasKey("AsImpL_BuildColliders"))
            {
                buildColliders = EditorPrefs.GetBool("AsImpL_BuildColliders");
            }
            if (EditorPrefs.HasKey("AsImpL_ColliderConvex"))
            {
                colliderConvex = EditorPrefs.GetBool("AsImpL_ColliderConvex");
            }
            if (EditorPrefs.HasKey("AsImpL_ColliderTrigger"))
            {
                colliderTrigger = EditorPrefs.GetBool("AsImpL_ColliderTrigger");
            }
#if !UNITY_2018_3_OR_NEWER
            if (EditorPrefs.HasKey("AsImpL_ColliderInflate"))
            {
                colliderInflate = EditorPrefs.GetBool("AsImpL_ColliderInflate");
            }
            if (EditorPrefs.HasKey("AsImpL_ColliderSkinWidth"))
            {
                colliderSkinWidth = EditorPrefs.GetFloat("AsImpL_ColliderSkinWidth");
            }
#endif
            if (EditorPrefs.HasKey("AsImpL_HideWhileLoading"))
            {
                hideWhileLoading = EditorPrefs.GetBool("AsImpL_HideWhileLoading");
            }
            if (EditorPrefs.HasKey("AsImpL_SplitByMaterial"))
            {
                splitByMaterial = EditorPrefs.GetBool("AsImpL_SplitByMaterial");
            }
            if (EditorPrefs.HasKey("AsImpL_ImportAssets"))
            {
                importAssets = EditorPrefs.GetBool("AsImpL_ImportAssets");
            }
            if (EditorPrefs.HasKey("AsImpL_AssetPath"))
            {
                importAssetPath = EditorPrefs.GetString("AsImpL_AssetPath");
            }
#if UNITY_2017_3_OR_NEWER
            if (EditorPrefs.HasKey("AsImpL_use32bitIndices"))
            {
                use32bitIndices = EditorPrefs.GetBool("AsImpL_use32bitIndices");
            }
#endif
        }


        private void OnEnable()
        {
            ResetSettings();
        }


        private void OnGUI()
        {
            EditorGUILayout.BeginHorizontal();
            defaultImportPath = EditorGUILayout.TextField("Default import path:", defaultImportPath);
            if (GUILayout.Button("...", GUILayout.Width(24), GUILayout.Height(15)))
            {
                defaultImportPath = EditorUtility.OpenFolderPanel("Select a folder", defaultImportPath, "");
                defaultImportPath = defaultImportPath.Replace('\\', '/');
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            lastPath = EditorGUILayout.TextField("OBJ file path:", lastPath);
            if (!string.IsNullOrEmpty(lastPath))
            {
                if (GUILayout.Button("^", GUILayout.Width(24), GUILayout.Height(15)))
                {
                    FileInfo fileInfo = new FileInfo(lastPath);
                    defaultImportPath = fileInfo.Directory.FullName;
                    defaultImportPath = defaultImportPath.Replace('\\', '/');
                }
            }
            if (GUILayout.Button("...", GUILayout.Width(24), GUILayout.Height(15)))
            {
                string[] filters = { "OBJ files", "obj", "All files", "*" };
                string absolutePath = EditorUtility.OpenFilePanelWithFilters("Load OBJ model", defaultImportPath, filters);
                if (!string.IsNullOrEmpty(absolutePath))
                {
                    FileInfo fileInfo = new FileInfo(absolutePath);
                    Debug.Log(fileInfo.Directory.FullName);
                    //EditorPrefs.SetString("OBJ Import path", fileInfo.Directory.FullName);
                    lastPath = absolutePath;
                }
            }
            EditorGUILayout.EndHorizontal();

            scale = EditorGUILayout.FloatField("Scale:", scale);
            convertUpAxis = EditorGUILayout.Toggle("Convert vertical axis", convertUpAxis);
            convertToDoubleSided = EditorGUILayout.Toggle("Convert to double-sided (duplicate&flip polygons)", convertToDoubleSided);
            litDiffuseMap = EditorGUILayout.Toggle("Lit diffuse map", litDiffuseMap);
            buildColliders = EditorGUILayout.Toggle("Generate mesh colliders", buildColliders);
            if (buildColliders)
            {
                colliderConvex = EditorGUILayout.Toggle("Convex mesh colliders", colliderConvex);
                if (colliderConvex)
                {
                    EditorGUILayout.HelpBox(
                        "Building convex meshes may not work for meshes with too many smooth surface regions.\n" +
                        "If you get errors find each involved object and fix its mesh collider (e.g. remove it or uncheck \"Convex\").",
                        MessageType.Warning);
                    colliderTrigger = EditorGUILayout.Toggle("Mesh colliders as trigger", colliderTrigger);
#if !UNITY_2018_3_OR_NEWER
                    colliderInflate = EditorGUILayout.Toggle("Mesh colliders inflated", colliderInflate);
                    colliderSkinWidth = EditorGUILayout.FloatField("Mesh colliders inflation amount", colliderSkinWidth);
#endif
                }
            }
#if UNITY_2017_3_OR_NEWER
            use32bitIndices = EditorGUILayout.Toggle("Use 32 bit indices", use32bitIndices);
#endif
            hideWhileLoading = EditorGUILayout.Toggle("Hide while loading", hideWhileLoading);
            splitByMaterial = EditorGUILayout.Toggle("Split by material", splitByMaterial);

            importAssets = EditorGUILayout.Toggle("Import assets", importAssets);
            if (importAssets)
            {
                importAssetPath = EditorGUILayout.TextField("OBJ asset path:", importAssetPath);
                importAssetPath = importAssetPath.Replace('\\', '/');
            }

            EditorGUILayout.Separator();

            EditorGUILayout.BeginHorizontal();
            if (GUILayout.Button("Reset settings", GUILayout.Width(100), GUILayout.Height(24)))
            {
                ResetSettings();
            }
            if (GUILayout.Button("Save settings", GUILayout.Width(100), GUILayout.Height(24)))
            {
                SaveSettings();
            }
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Import", GUILayout.Width(80), GUILayout.Height(24)))
            {
                lastPath = lastPath.Replace('\\', '/');
                string absolute_path = lastPath;
                if (!string.IsNullOrEmpty(absolute_path))
                {
                    objObject = new GameObject();
                    objObject.name = "OBJ Loader";
                    objImporter = objObject.AddComponent<ObjectImporter>();
                    objImporter.importAssets = importAssets;
                    objImporter.importAssetPath = importAssetPath;

                    GameObject parentObject = Selection.activeObject as GameObject;
                    if (parentObject && !parentObject.activeInHierarchy)
                    {
                        parentObject = null;
                    }
                    ImportOptions opt = new ImportOptions();
                    opt.zUp = convertUpAxis;
                    opt.litDiffuse = litDiffuseMap;
                    opt.convertToDoubleSided = convertToDoubleSided;
                    opt.modelScaling = scale;
                    opt.buildColliders = buildColliders;
                    opt.colliderTrigger = colliderTrigger;
                    opt.colliderConvex = colliderConvex;
#if !UNITY_2018_3_OR_NEWER
                    opt.colliderInflate = colliderInflate;
                    opt.colliderSkinWidth = colliderSkinWidth;
#endif
                    opt.hideWhileLoading = hideWhileLoading;
                    opt.splitByMaterial = splitByMaterial;
                    objImporter.ImportFile(absolute_path, parentObject ? parentObject.transform : null, opt);
                    loading = true;
                }
            }
            if (GUILayout.Button("Cancel", GUILayout.Width(80), GUILayout.Height(24)))
            {
                EditorUtility.ClearProgressBar();
                if (loading)
                {
                    if (objObject) DestroyImmediate(objObject);
                    loading = false;
                }
                Close();
            }
            EditorGUILayout.EndHorizontal();
        }


        private void Update()
        {
            if (objObject && objImporter && loading)
            {
                // force an update to let coroutine run
                // TODO: find a better way
                objObject.transform.localPosition = Vector3.one * 0.001f;
                objObject.transform.localPosition = Vector3.zero;
                objImporter.UpdateStatus();

                //loading = (ObjLoader.totalProgress.fileProgress.Count > 0);
                float progress = 0;
                string title = string.Empty;
                string msg = string.Empty;
                // TODO: check if an exception occurred in one or more loaders and clear the progress bar
                if (objImporter.AllImported)
                {
                    // done
                    FileInfo fileInfo = new FileInfo(lastPath);
                    string fileName = fileInfo.Name;
                    GameObject loadedObj = LoaderObj.GetModelByPath(lastPath);
                    if (loadedObj)
                    {
                        // detach the loaded object from the importer in case no custom parent object is provided
                        if (objObject.transform.childCount > 0 && loadedObj == objObject.transform.GetChild(0).gameObject)
                        {
                            loadedObj.transform.SetParent(null, false);
                        }
                        Undo.RegisterCreatedObjectUndo(loadedObj, "Import OBJ");
                        Selection.activeObject = loadedObj;
                        DestroyImmediate(objObject);
                        EditorUtility.ClearProgressBar();
                        loading = false;
                        Close();
                    }
                }
                else
                {
                    progress = objImporter.ImportProgress;
                    if (progress > 0)
                    {
                        if (progress >= 100f)
                        {
                            title = "Wait please...";
                            msg = "Finalizing...";
                        }
                        else
                        {
                            title = "Importing " + ((int)progress).ToString() + "%";
                            msg = objImporter.ImportMessage;
                        }
                        EditorUtility.DisplayProgressBar(title, msg, progress / 100f);
                    }
                }
            }
        }


        private void OnInspectorUpdate()
        {
            Repaint();
        }
    }
}


================================================
FILE: Assets/AsImpL/Scripts/Editor/ObjImportWindow.cs.meta
================================================
fileFormatVersion: 2
guid: 7edf263ef720bd04a94de49c8b447803
timeCreated: 1486545119
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Editor.meta
================================================
fileFormatVersion: 2
guid: 09c5fcb0a17ffac489974fabba22e67d
folderAsset: yes
timeCreated: 1486633204
licenseType: Free
DefaultImporter:
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/EditorUtil.cs
================================================
#if UNITY_EDITOR
using System;
using System.IO;
using UnityEngine;
using UnityEditor;

namespace AsImpL
{
    public class EditorUtil
    {
        /// <summary>
        /// Create a folder, if not yet created, in the asset database
        /// </summary>
        /// <param name="path">path that will contain the new folder</param>
        /// <param name="folder">name of the folder</param>
        public static void CreateAssetFolder(string path, string folder)
        {
            if (!AssetDatabase.IsValidFolder(path + "/" + folder))
            {
                AssetDatabase.CreateFolder(path, folder);
            }
        }


        /// <summary>
        /// Capture a screenshot, naming its file automatically with date and time,
        /// then shows the file in the file manager (e.g. Explorer)
        /// </summary>
        /// <param name="prefix">prefix at the beginning of the file name</param>
        public static void AutoCaptureScreenshot(string prefix)
        {
            string fileName = prefix + "-" + DateTime.Now.ToString("s").Replace('T', '_').Replace(':', '-') + ".png";
#if UNITY_2017_1_OR_NEWER
            ScreenCapture.CaptureScreenshot(fileName);
#else
            Application.CaptureScreenshot(fileName);
#endif
            Debug.Log("Screenshot saved to " + Application.dataPath + "/" + fileName);
            EditorUtility.RevealInFinder(Application.dataPath);
        }


        /// <summary>
        /// Set a texture in the asset database as readable to perform image analisys
        /// </summary>
        /// <param name="texAssetPath"></param>
        public static void SetTextureReadable(string texAssetPath)
        {
            TextureImporter textureImporter = AssetImporter.GetAtPath(texAssetPath) as TextureImporter;
            if (textureImporter)
            {
                Debug.LogFormat("Changing import settings for texture {0}...", texAssetPath);
                textureImporter.isReadable = true;
                textureImporter.alphaIsTransparency = true;
                textureImporter.SaveAndReimport();
            }
            else
            {
                Debug.LogError("Texture importer for not found for " + texAssetPath);
            }
        }


        /// <summary>
        /// Save a new texture to the asset databse and reimport it
        /// </summary>
        /// <param name="texture">new texture</param>
        /// <param name="texAssetPath">path in the asset database</param>
        /// <param name="postFix">postfix appended to the file name</param>
        /// <param name="isNormalMap">if true the texture importer is set to normal map</param>
        public static void SaveAndReimportPngTexture(ref Texture2D texture, string texAssetPath, string postFix, bool isNormalMap = false)
        {
            string newTexAssetPath = Path.GetDirectoryName(texAssetPath) + "/" + Path.GetFileNameWithoutExtension(texAssetPath) + postFix + ".png";
            if (newTexAssetPath != texAssetPath)
            {
                Debug.LogFormat("Storing texture {0}...", newTexAssetPath);
                // Encode texture into PNG
                byte[] bytes = texture.EncodeToPNG();
                File.WriteAllBytes(Application.dataPath + "/../" + newTexAssetPath, bytes);
                //texture.LoadImage(bytes, false);
                //AssetDatabase.CreateAsset(texture, newTexAssetPath);
                //AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
                //EditorUtil.SetTextureReadable(texture, newTexAssetPath);
                texAssetPath = newTexAssetPath;
                if (isNormalMap)
                {
                    TextureImporter newTextureImporter = AssetImporter.GetAtPath(texAssetPath) as TextureImporter;
                    newTextureImporter.textureType = TextureImporterType.NormalMap;
                    newTextureImporter.SaveAndReimport();
                }
                //newTextureImporter.isReadable = true;
                //AssetDatabase.CreateAsset(newTextureImporter, newTexAssetPath);
                texture = AssetDatabase.LoadAssetAtPath<Texture2D>(texAssetPath);
            }
        }

    }
}
#endif


================================================
FILE: Assets/AsImpL/Scripts/EditorUtil.cs.meta
================================================
fileFormatVersion: 2
guid: dda14eb2e4479a44d88bb9c9466c1eef
timeCreated: 1488362452
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/IO/FileFilesystem.cs
================================================
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;

namespace AsImpL
{
    /// <summary>
    /// Filesystem implementation that uses the standard .NET File class.
    /// </summary>
    public class FileFilesystem : IFilesystem
    {
        public byte[] ReadAllBytes(string path)
        {
            return File.ReadAllBytes(path);
        }

        public string[] ReadAllLines(string path)
        {
            return File.ReadAllLines(path);
        }

        public FileStream OpenRead(string path)
        {
            return File.OpenRead(path);
        }

        public IEnumerator DownloadUri(string uri, bool notifyErrors)
        {
#if UNITY_2018_3_OR_NEWER
            UnityWebRequest uwr = UnityWebRequest.Get(uri);
            yield return uwr.SendWebRequest();

#if UNITY_2020_2_OR_NEWER
            if (uwr.result == UnityWebRequest.Result.ConnectionError)
#else
            if (uwr.isNetworkError || uwr.isHttpError)
#endif
            {
                if (notifyErrors)
                {
                    Debug.LogError(uwr.error);
                }

                yield return null;
            }
            else
            {
                // Get downloaded asset bundle
                yield return uwr.downloadHandler.text;
            }
#else
            WWW www = new WWW(uri);
            yield return www;
            if (www.error != null)
            {
                if (notifyErrors)
                {
                    Debug.LogError("Error loading " + uri + "\n" + www.error);
                }

                yield return null;
            }
            else
            {
                yield return www.text;
            }
#endif
        }

        public IEnumerator DownloadTexture(string uri)
        {
#if UNITY_2018_3_OR_NEWER
            using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(uri))
            {
                yield return uwr.SendWebRequest();

#if UNITY_2020_2_OR_NEWER
                if (uwr.result == UnityWebRequest.Result.ConnectionError)
#else
                if (uwr.isNetworkError || uwr.isHttpError)
#endif
                {
                    Debug.LogError(uwr.error);
                    yield return null;
                }
                else
                {
                    // Get downloaded asset bundle
                    yield return DownloadHandlerTexture.GetContent(uwr);
                }
            }
#else
            WWW loader = new WWW(uri);
            yield return loader;

            if (loader.error != null)
            {
                Debug.LogError(loader.error);
                yield return null;
            }
            else
            {
                yield return LoadTexture(loader);
            }
#endif
        }

#if !UNITY_2018_3_OR_NEWER
        /// <summary>
        /// Load a texture from the URL got from the parameter.
        /// </summary>
        private Texture2D LoadTexture(WWW loader)
        {
            string ext = Path.GetExtension(loader.url).ToLower();
            Texture2D tex = null;

            // TODO: add support for more formats (bmp, gif, dds, ...)
            if (ext == ".tga")
            {
                tex = TextureLoader.LoadTextureFromUrl(loader.url);
                //tex = TgaLoader.LoadTGA(new MemoryStream(loader.bytes));
            }
            else if (ext == ".png" || ext == ".jpg" || ext == ".jpeg")
            {
                tex = loader.texture;
            }
            else
            {
                Debug.LogWarning("Unsupported texture format: " + ext);
            }

            if (tex == null)
            {
                Debug.LogErrorFormat("Failed to load texture {0}", loader.url);
            }
            else
            {
                //tex.alphaIsTransparency = true;
                //tex.filterMode = FilterMode.Trilinear;
            }

            return tex;
        }
#endif
    }
}

================================================
FILE: Assets/AsImpL/Scripts/IO/FileFilesystem.cs.meta
================================================
fileFormatVersion: 2
guid: 56918d1d8d26c6b488ec48ff28fe0dd7
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/IO/IFilesystem.cs
================================================
using System.Collections;
using System.IO;

namespace AsImpL
{
    /// <summary>
    /// Interface for classes that access the filesystem.
    /// </summary>
    public interface IFilesystem
    {
        /// <summary>
        /// Reads all data from the specified path into a byte array.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        byte[] ReadAllBytes(string path);

        /// <summary>
        /// Reads all lines in the specified file into an array of strings.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        string[] ReadAllLines(string path);

        /// <summary>
        /// Opens the file at the specified path for reading.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        FileStream OpenRead(string path);

        /// <summary>
        /// Downloads the specified URI.
        /// </summary>
        /// <param name="uri">The URI to download.</param>
        /// <param name="notifyErrors">Whether to notify of errors.</param>
        /// <returns>An enumerator usable as Coroutine in Unity.</returns>
        IEnumerator DownloadUri(string uri, bool notifyErrors);

        /// <summary>
        /// Downloads the specified URI as texture.
        /// </summary>
        /// <param name="uri">The URI to download.</param>
        /// <returns>An enumerator usable as Coroutine in Unity.</returns>
        IEnumerator DownloadTexture(string uri);
    }
}

================================================
FILE: Assets/AsImpL/Scripts/IO/IFilesystem.cs.meta
================================================
fileFormatVersion: 2
guid: 79a86b82a4f3ce7429ef221b36a9669e
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/IO.meta
================================================
fileFormatVersion: 2
guid: b4f2254e567d40540b17ed7bb78df22a
folderAsset: yes
DefaultImporter:
  externalObjects: {}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/ImportOptions.cs
================================================
using UnityEngine;

namespace AsImpL
{
    [System.Serializable]
    /// <summary>
    /// Options to define how the model will be loaded and imported.
    /// </summary>
    public class ImportOptions
    {
        [Tooltip("Load the OBJ file assuming Z as vertical axis (instead of Y)")]
        public bool zUp = true;

        [Tooltip("Consider diffuse map as already lit (disable lighting) if no other texture is present")]
        public bool litDiffuse = false;

        [Tooltip("Consider to double-sided (duplicate and flip faces and normals")]
        public bool convertToDoubleSided = false;

        [Tooltip("Rescaling for the model (1 = no rescaling)")]
        public float modelScaling = 1f;

        [Tooltip("Reuse a model in memory if already loaded")]
        public bool reuseLoaded = false;

        [Tooltip("Inherit parent layer")]
        public bool inheritLayer = false;

        [Tooltip("Generate mesh colliders")]
        public bool buildColliders = false;

        [Tooltip("Generate convex mesh colliders (only active if buildColliders = true)\nNote: it could not work for meshes with too many smooth surface regions.")]
        public bool colliderConvex = false;

        [Tooltip("Mesh colliders as trigger (only active if colliderConvex = true)")]
        public bool colliderTrigger = false;

#if !UNITY_2018_3_OR_NEWER
        [Tooltip("Mesh colliders inflated (only active if colliderConvex = true)")]
        public bool colliderInflate = false;

        [Tooltip("Mesh colliders inflation amount (only active if colliderInflate = true)")]
        public float colliderSkinWidth = 0.01f;
#endif

#if UNITY_2017_3_OR_NEWER
        [Tooltip("Use 32 bit indices when needed, if available")]
        public bool use32bitIndices = true;
#endif

        [Tooltip("Hide the loaded object during the loading process")]
        public bool hideWhileLoading = false;

        [Tooltip("Split meshes by material")]
        public bool splitByMaterial = false;

        [Header("Local Transform for the imported game object")]
        [Tooltip("Position of the object")]
        public Vector3 localPosition = Vector3.zero;

        [Tooltip("Rotation of the object\n(Euler angles)")]
        public Vector3 localEulerAngles = Vector3.zero;

        [Tooltip("Scaling of the object\n([1,1,1] = no rescaling)")]
        public Vector3 localScale = Vector3.one;
    }
}


================================================
FILE: Assets/AsImpL/Scripts/ImportOptions.cs.meta
================================================
fileFormatVersion: 2
guid: cb0228fe32d671f4e9d1e444c02da369
timeCreated: 1488270546
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Loaders/Loader.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
#if UNITY_EDITOR
using UnityEditor;
#endif

/// <summary>
/// Asynchronous importer and loader
/// </summary>
namespace AsImpL
{

    /// <summary>
    /// Abstract loader to be used as a base class for specific loaders.
    /// </summary>
    public abstract class Loader : MonoBehaviour
    {
        /// <summary>
        /// Total loading progress, for all the models currently loading.
        /// </summary>
        public static LoadingProgress totalProgress = new LoadingProgress();

        /// <summary>
        /// Options to define how the model will be loaded and imported.
        /// </summary>
        public ImportOptions buildOptions;

#if UNITY_EDITOR
        /// <summary>
        /// Alternative texture path: if not null textures will be loaded from here.
        /// </summary>
        public string altTexPath = null;
#endif

        // raw subdivision in percentages of the loading phases (empirically computed loading a large sample OBJ file)
        // TODO: refine or change this method
        protected static float LOAD_PHASE_PERC = 8f;
        protected static float TEXTURE_PHASE_PERC = 1f;
        protected static float MATERIAL_PHASE_PERC = 1f;
        protected static float BUILD_PHASE_PERC = 90f;

        protected static Dictionary<string, GameObject> loadedModels = new Dictionary<string, GameObject>();
        protected static Dictionary<string, int> instanceCount = new Dictionary<string, int>();

        protected DataSet dataSet = new DataSet();
        protected ObjectBuilder objectBuilder = null;

        /// <summary>
        /// Warning! This will be removed soon to avoid confusion between
        /// the ObjectBuilder class and this property, use Builder property instead.
        /// </summary>
		[Obsolete("ObjectBuilder property is deprecated, please use Builder instead.")]
        public ObjectBuilder ObjectBuilder
        {
            get { return objectBuilder ?? (objectBuilder = new ObjectBuilder()); }
            set { objectBuilder = value; }
        }

        protected List<MaterialData> materialData;

        protected SingleLoadingProgress objLoadingProgress = new SingleLoadingProgress();

        protected Stats loadStats;

        private Texture2D loadedTexture = null;


        /// <summary>
        /// Object used to build the game object hierarchy (it is created if not previously set).
        /// </summary>
        public ObjectBuilder Builder
        {
            get { return objectBuilder ?? (objectBuilder = new ObjectBuilder()); }
            set { objectBuilder = value; }
        }

        /// <summary>
        /// Load the file assuming its vertical axis is Z instead of Y 
        /// </summary>
        public bool ConvertVertAxis
        {
            get
            {
                return buildOptions != null ? buildOptions.zUp : false;
            }
            set
            {
                if (buildOptions == null)
                {
                    buildOptions = new ImportOptions();
                }
                buildOptions.zUp = value;
            }
        }


        /// <summary>
        /// Rescaling for the model (1 = no rescaling)
        /// </summary>
        public float Scaling
        {
            get
            {
                return buildOptions != null ? buildOptions.modelScaling : 1f;
            }
            set
            {
                if (buildOptions == null)
                {
                    buildOptions = new ImportOptions();
                }
                buildOptions.modelScaling = value;
            }
        }

        private IFilesystem _filesystem = null;
        public IFilesystem Filesystem
        {
            get
            {
                if (_filesystem == null)
                {
                    _filesystem = new FileFilesystem();
                }

                return _filesystem;
            }

            set
            {
                _filesystem = value;
            }
        }


        /// <summary>
        /// Check if a material library is defined for this model
        /// </summary>
        protected abstract bool HasMaterialLibrary { get; }

#if UNITY_EDITOR
        /// <summary>
        /// Import data as assets in the project (Editor only)
        /// </summary>
        public bool ImportingAssets { get { return !string.IsNullOrEmpty(altTexPath); } }
#endif

        /// <summary>
        /// Event triggered when an object is created.
        /// </summary>
        public event Action<GameObject, string> ModelCreated;

        /// <summary>
        /// Event triggered when an object is successfully loaded.
        /// </summary>
        public event Action<GameObject, string> ModelLoaded;

        /// <summary>
        /// Event triggered if failed to load an object
        /// </summary>
        public event Action<string> ModelError;


        /// <summary>
        /// Get a previously loaded model by its absolute path
        /// </summary>
        /// <param name="absolutePath">absolute path used to load the model</param>
        /// <returns>The game object previously loaded</returns>
        public static GameObject GetModelByPath(string absolutePath)
        {
            if (loadedModels.ContainsKey(absolutePath))
            {
                return loadedModels[absolutePath];
            }
            return null;
        }


        /// <summary>
        /// Load a model.
        /// </summary>
        /// <param name="objName">name of the GameObject, if empty use file name</param>
        /// <param name="absolutePath">absolute file path</param>
        /// <param name="parentObj">Transform to which attach the loaded object (null=scene)</param>
        /// <returns>You can use StartCoroutine( loader.Load(...) )</returns>
        public IEnumerator Load(string objName, string absolutePath, Transform parentObj)
        {
            string fileName = Path.GetFileName(absolutePath);
            string fileNameNoExt = Path.GetFileNameWithoutExtension(absolutePath);
            string name = objName;
            if (name == null || name == "") objName = fileNameNoExt;

            totalProgress.singleProgress.Add(objLoadingProgress);
            objLoadingProgress.fileName = fileName;
            objLoadingProgress.error = false;
            objLoadingProgress.message = "Loading " + fileName + "...";
            Debug.LogFormat("Loading {0}\n  from: {1}...", objName, absolutePath);

            yield return null;

            string normalizedPath = absolutePath.Replace('\\', '/');


            // TODO: implementation of a caching mechanism for models downloaded from an URL

            // if the model was already loaded duplicate the existing object
            if (buildOptions != null && buildOptions.reuseLoaded && loadedModels.ContainsKey(normalizedPath) && loadedModels[normalizedPath] != null)
            {
                Debug.LogFormat("File {0} already loaded, creating instance.", normalizedPath);
                instanceCount[normalizedPath]++;
                if (name == null || name == "") objName = objName + "_" + instanceCount[normalizedPath];
                objLoadingProgress.message = "Instantiating " + objName + "...";
                while (loadedModels[normalizedPath] == null)
                {
                    yield return null;
                }


                GameObject newObj = Instantiate(loadedModels[normalizedPath]);
                yield return newObj;
                OnCreated(newObj, absolutePath);
                newObj.name = objName;

                if (parentObj != null) newObj.transform.parent = parentObj.transform;
                totalProgress.singleProgress.Remove(objLoadingProgress);
                OnLoaded(newObj, absolutePath);
                yield break;
            }
            loadedModels[normalizedPath] = null; // define a key for the dictionary
            instanceCount[normalizedPath] = 0; // define a key for the dictionary

            float lastTime = Time.realtimeSinceStartup;
            float startTime = lastTime;
            yield return LoadModelFile(normalizedPath);
            loadStats.modelParseTime = Time.realtimeSinceStartup - lastTime;

            if (objLoadingProgress.error)
            {
                OnLoadFailed(absolutePath);
                yield break;
            }

            lastTime = Time.realtimeSinceStartup;
            if (HasMaterialLibrary)
            {
                yield return LoadMaterialLibrary(normalizedPath);
            }
            loadStats.materialsParseTime = Time.realtimeSinceStartup - lastTime;
            lastTime = Time.realtimeSinceStartup;
            yield return Build(normalizedPath, objName, parentObj);
            loadStats.buildTime = Time.realtimeSinceStartup - lastTime;
            loadStats.totalTime = Time.realtimeSinceStartup - startTime;
            Debug.Log("Done: " + objName
                + "\n  Loaded in " + loadStats.totalTime + " seconds"
                + "\n  Model data parsed in " + loadStats.modelParseTime + " seconds"
                + "\n  Material data parsed in " + loadStats.materialsParseTime + " seconds"
                + "\n  Game objects built in " + loadStats.buildTime + " seconds"
                + "\n    textures: " + loadStats.buildStats.texturesTime + " seconds"
                + "\n    materials: " + loadStats.buildStats.materialsTime + " seconds"
                + "\n    objects: " + loadStats.buildStats.objectsTime + " seconds"
                );
            totalProgress.singleProgress.Remove(objLoadingProgress);
            OnLoaded(loadedModels[normalizedPath], absolutePath);
        }


        /// <summary>
        /// Parse the model to get a list of the paths of all used textures
        /// </summary>
        /// <param name="absolutePath">absolute path of the model</param>
        /// <returns>List of paths of the textures referenced by the model</returns>
        public abstract string[] ParseTexturePaths(string absolutePath);

        /// <summary>
        /// Load the main model file
        /// </summary>
        /// <param name="absolutePath">absolute file path</param>
        /// <remarks>This is called by Load() method</remarks>
        protected abstract IEnumerator LoadModelFile(string absolutePath);

        /// <summary>
        /// Load the material library from the given path.
        /// </summary>
        /// <param name="absolutePath">absolute file path</param>
        /// <remarks>This is called by Load() method</remarks>
        protected abstract IEnumerator LoadMaterialLibrary(string absolutePath);


        /// <summary>
        /// Build the game objects from data set, materials and textures.
        /// </summary>
        /// <param name="absolutePath">absolute file path</param>
        /// <param name="objName">Name of the main game object (model root)</param>
        /// <param name="parentTransform">transform to which the model root will be attached (if null it will be a root aobject)</param>
        /// <remarks>This is called by Load() method</remarks>
        protected IEnumerator Build(string absolutePath, string objName, Transform parentTransform)
        {
            float prevTime = Time.realtimeSinceStartup;
            GameObject newObj = new GameObject(objName);
            if (buildOptions.hideWhileLoading)
            {
                newObj.SetActive(false);
            }
            if (parentTransform != null) newObj.transform.SetParent(parentTransform.transform, false);
            ModelReferences modelRefs = newObj.AddComponent<ModelReferences>();
            OnCreated(newObj, absolutePath);

            if (materialData != null)
            {
                string basePath = GetDirName(absolutePath);
                objLoadingProgress.message = "Loading textures...";
                int count = 0;
                foreach (MaterialData mtl in materialData)
                {
                    objLoadingProgress.percentage = LOAD_PHASE_PERC + TEXTURE_PHASE_PERC * count / materialData.Count;
                    count++;
                    if (mtl.diffuseTexPath != null)
                    {
#if UNITY_EDITOR
                        if (ImportingAssets)
                        {
                            mtl.diffuseTex = LoadAssetTexture(mtl.diffuseTexPath);
                        }
                        else
#endif
                        {
                            yield return LoadMaterialTexture(basePath, mtl.diffuseTexPath);
                            mtl.diffuseTex = loadedTexture;
                        }
                        modelRefs.AddTexture(mtl.diffuseTex);
                    }

                    if (mtl.bumpTexPath != null)
                    {
#if UNITY_EDITOR
                        if (ImportingAssets)
                        {
                            mtl.bumpTex = LoadAssetTexture(mtl.bumpTexPath);
                        }
                        else
#endif
                        {
                            yield return LoadMaterialTexture(basePath, mtl.bumpTexPath);
                            mtl.bumpTex = loadedTexture;
                        }
                        modelRefs.AddTexture(mtl.bumpTex);
                    }

                    if (mtl.specularTexPath != null)
                    {
#if UNITY_EDITOR
                        if (ImportingAssets)
                        {
                            mtl.specularTex = LoadAssetTexture(mtl.specularTexPath);
                        }
                        else
#endif
                        {
                            yield return LoadMaterialTexture(basePath, mtl.specularTexPath);
                            mtl.specularTex = loadedTexture;
                        }
                        modelRefs.AddTexture(mtl.specularTex);
                    }

                    if (mtl.opacityTexPath != null)
                    {
#if UNITY_EDITOR
                        if (ImportingAssets)
                        {
                            mtl.opacityTex = LoadAssetTexture(mtl.opacityTexPath);
                        }
                        else
#endif
                        {
                            yield return LoadMaterialTexture(basePath, mtl.opacityTexPath);
                            mtl.opacityTex = loadedTexture;
                        }
                        modelRefs.AddTexture(mtl.opacityTex);
                    }
                }
            }
            loadStats.buildStats.texturesTime = Time.realtimeSinceStartup - prevTime;
            prevTime = Time.realtimeSinceStartup;

            ObjectBuilder.ProgressInfo info = new ObjectBuilder.ProgressInfo();

            objLoadingProgress.message = "Loading materials...";
            yield return null;
#if UNITY_EDITOR
            Builder.alternativeTexPath = altTexPath;
#endif
            Builder.buildOptions = buildOptions;
            bool hasColors = dataSet.colorList.Count > 0;
            bool hasMaterials = materialData != null;
            Builder.InitBuildMaterials(materialData, hasColors, modelRefs);
            float objInitPerc = objLoadingProgress.percentage;
            if (hasMaterials)
            {
                while (Builder.BuildMaterials(info, modelRefs))
                {
                    objLoadingProgress.percentage = objInitPerc + MATERIAL_PHASE_PERC * Builder.NumImportedMaterials / materialData.Count;
                    yield return null;
                }
                loadStats.buildStats.materialsTime = Time.realtimeSinceStartup - prevTime;
                prevTime = Time.realtimeSinceStartup;
            }

            objLoadingProgress.message = "Building scene objects...";

           ////newObj.transform.localScale = Vector3.one * Scaling;
            float initProgress = objLoadingProgress.percentage;
            Builder.StartBuildObjectAsync(dataSet, newObj);
            while (Builder.BuildObjectAsync(ref info))
            {
                objLoadingProgress.message = "Building scene objects... " + (info.objectsLoaded + info.groupsLoaded) + "/" + (dataSet.objectList.Count + info.numGroups);
                objLoadingProgress.percentage = initProgress + BUILD_PHASE_PERC * (info.objectsLoaded / dataSet.objectList.Count + (float)info.groupsLoaded / info.numGroups);
                yield return null;
            }
            objLoadingProgress.percentage = 100.0f;
            loadedModels[absolutePath] = newObj;
            loadStats.buildStats.objectsTime = Time.realtimeSinceStartup - prevTime;
        }


        /// <summary>
        /// Get the directory name of the given path, appending the final slash if eeded.
        /// </summary>
        /// <param name="absolutePath">the absolute path</param>
        /// <returns>the directory name ending with `/`</returns>
        protected string GetDirName(string absolutePath)
        {
            string basePath;
            if (absolutePath.Contains("//"))
            {
                basePath = absolutePath.Remove(absolutePath.LastIndexOf('/') + 1);
            }
            else
            {
                string dirName = Path.GetDirectoryName(absolutePath);
                basePath = string.IsNullOrEmpty(dirName) ? "" : dirName;
                if (!basePath.EndsWith("/"))
                {
                    basePath += "/";
                }
            }
            return basePath;
        }


        protected virtual void OnLoaded(GameObject obj, string absolutePath)
        {
            if (obj == null)
            {
                if (ModelError != null)
                {
                    ModelError(absolutePath);
                }
            }
            else
            {
                if (buildOptions != null)
                {
                    obj.transform.localPosition = buildOptions.localPosition;
                    obj.transform.localRotation = Quaternion.Euler(buildOptions.localEulerAngles); ;
                    obj.transform.localScale = buildOptions.localScale;
                    if (buildOptions.inheritLayer)
                    {
                        obj.layer = obj.transform.parent.gameObject.layer;
                        MeshRenderer[] mrs = obj.transform.GetComponentsInChildren<MeshRenderer>(true);
                        for (int i = 0; i < mrs.Length; i++)
                        {
                            mrs[i].gameObject.layer = obj.transform.parent.gameObject.layer;
                        }
                    }
                }
                if (buildOptions.hideWhileLoading)
                {
                    obj.SetActive(true);
                }

                if (ModelLoaded != null)
                {
                    ModelLoaded(obj, absolutePath);
                }
            }
        }


        protected virtual void OnCreated(GameObject obj, string absolutePath)
        {
            if (obj == null)
            {
                if (ModelError != null)
                {
                    ModelError(absolutePath);
                }
            }
            else
            {
                if (ModelCreated != null)
                {
                    ModelCreated(obj, absolutePath);
                }
            }
        }


        protected virtual void OnLoadFailed(string absolutePath)
        {
            if (ModelError != null)
            {
                ModelError(absolutePath);
            }
        }


#if UNITY_EDITOR
        /// <summary>
        /// Load a texture from the asset database
        /// </summary>
        /// <param name="texturePath">texture path inside the asset database</param>
        /// <returns>the loaded texture or null on error</returns>
        private Texture2D LoadAssetTexture(string texturePath)
        {
            FileInfo textFileInfo = new FileInfo(texturePath);
            string texpath = altTexPath + textFileInfo.Name;
            texpath = texpath.Replace("//", "/");
            Debug.LogFormat("Loading texture asset '{0}'", texpath);
            return AssetDatabase.LoadAssetAtPath<Texture2D>(texpath);
        }
#endif


        /// <summary>
        /// Convert a texture path to a texture URL and update the progress message
        /// </summary>
        /// <param name="basePath">base texture path</param>
        /// <param name="texturePath">relative texture path</param>
        /// <returns>URL of the texture</returns>
        private string GetTextureUrl(string basePath, string texturePath)
        {
            string texPath = texturePath.Replace("\\", "/").Replace("//", "/");
            if (!Path.IsPathRooted(texPath))
            {
                texPath = basePath + texturePath;
            }
            if (!texPath.Contains("//"))
            {
                texPath = "file:///" + texPath;
            }
            objLoadingProgress.message = "Loading textures...\n" + texPath;
            return texPath;
        }


        private IEnumerator LoadMaterialTexture(string basePath, string path)
        {
            loadedTexture = null;
            string texPath = GetTextureUrl(basePath, path);

            var enumerable = Filesystem.DownloadTexture(texPath);

            yield return enumerable;

            if (enumerable.Current != null)
            {
                loadedTexture = (Texture2D)enumerable.Current;
            }
        }


        /// <summary>
        /// Load a texture from the URL got from the parameter.
        /// </summary>
#if UNITY_2018_3_OR_NEWER
        private Texture2D LoadTexture(UnityWebRequest loader)
#else
        private Texture2D LoadTexture(WWW loader)
#endif
        {
            string ext = Path.GetExtension(loader.url).ToLower();
            Texture2D tex = null;

            // TODO: add support for more formats (bmp, gif, dds, ...)
            if (ext == ".tga")
            {
                tex = TextureLoader.LoadTextureFromUrl(loader.url);
                //tex = TgaLoader.LoadTGA(new MemoryStream(loader.bytes));
            }
            else if (ext == ".png" || ext == ".jpg" || ext == ".jpeg")
            {
#if UNITY_2018_3_OR_NEWER
                tex = DownloadHandlerTexture.GetContent(loader);
#else
                tex = loader.texture;
#endif
            }
            else
            {
                Debug.LogWarning("Unsupported texture format: " + ext);
            }

            if (tex == null)
            {
                Debug.LogErrorFormat("Failed to load texture {0}", loader.url);
            }
            else
            {
                //tex.alphaIsTransparency = true;
                //tex.filterMode = FilterMode.Trilinear;
            }

            return tex;
        }


        protected struct BuildStats
        {
            public float texturesTime;
            public float materialsTime;
            public float objectsTime;
        }


        protected struct Stats
        {
            public float modelParseTime;
            public float materialsParseTime;
            public float buildTime;
            public BuildStats buildStats;
            public float totalTime;
        }
    }
}


================================================
FILE: Assets/AsImpL/Scripts/Loaders/Loader.cs.meta
================================================
fileFormatVersion: 2
guid: e11055a82efa5854bb71067ff3835d61
timeCreated: 1487939407
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Loaders/LoaderObj.cs
================================================
using UnityEngine;
using UnityEngine.Networking;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.IO;
using System.Globalization;

namespace AsImpL
{
    /// <summary>
    /// Class for loading OBJ files into Unity scene at run-time and in editor mode.
    /// </summary>
    /// <remarks>
    /// Partially derived from "Runtime OBJ Loader"
    /// (http://forum.unity3d.com/threads/free-runtime-obj-loader.365884/)
    /// and from "runtime .OBJ file loader for Unity3D"
    /// (https://github.com/hammmm/unity-obj-loader) and 
    /// (https://github.com/cmdr2/unity-remote-obj-loader)
    /// 
    /// New features:
    /// <list type="bullet">
    /// <item><description>meshes with more than 65K vertices/indices are split and loaded</description></item>
    /// <item><description>groups are loaded into game (sub) objects</description></item>
    /// <item><description>extended material support</description></item>
    /// <item><description>computation of normal maps and tangents</description></item>
    /// <item><description>computation of albedo texture from diffuse and opacity textures</description></item>
    /// <item><description>progressive loading</description></item>
    /// <item><description>reusing data for multiple objects</description></item>
    /// <item><description>create a loader for each model for parallel loading</description></item>
    /// <item><description>support for asset import</description></item>
    /// </list>
    /// <seealso cref="DataSet"/>
    /// <seealso cref="MaterialData"/>
    /// <seealso cref="ObjectBuilder"/>
    /// </remarks>
    public class LoaderObj : Loader
    {
        private string mtlLib;
        private string loadedText;


        /// <summary>
        /// Parse dependencies of the given OBJ file.
        /// </summary>
        /// <param name="absolutePath">absolute file path</param>
        /// <returns>The list of dependencies (textures files, if any).</returns>
        public override string[] ParseTexturePaths(string absolutePath)
        {
            List<string> mtlTexPathList = new List<string>();
            string basePath = GetDirName(absolutePath);

            string mtlLibName = ParseMaterialLibName(absolutePath);

            if (!string.IsNullOrEmpty(mtlLibName))
            {
                //mtlDepPathList.Add(mtlLibName);
                string mtlPath = basePath + mtlLibName;
                string[] lines = Filesystem.ReadAllLines(mtlPath);
                List<MaterialData> mtlData = new List<MaterialData>();
                ParseMaterialData(lines, mtlData);
                foreach (MaterialData mtl in mtlData)
                {
                    if (!string.IsNullOrEmpty(mtl.diffuseTexPath))
                    {
                        mtlTexPathList.Add(mtl.diffuseTexPath);
                    }
                    if (!string.IsNullOrEmpty(mtl.specularTexPath))
                    {
                        mtlTexPathList.Add(mtl.specularTexPath);
                    }
                    if (!string.IsNullOrEmpty(mtl.bumpTexPath))
                    {
                        mtlTexPathList.Add(mtl.bumpTexPath);
                    }
                    if (!string.IsNullOrEmpty(mtl.opacityTexPath))
                    {
                        mtlTexPathList.Add(mtl.opacityTexPath);
                    }
                }
            }

            return mtlTexPathList.ToArray();
        }


        protected override IEnumerator LoadModelFile(string absolutePath)
        {
            string url = absolutePath.Contains("//") ? absolutePath : "file:///" + absolutePath;
            yield return LoadOrDownloadText(url);

            if (string.IsNullOrEmpty(loadedText))
            {
                // loading errors are already notified by LoadOrDownloadText()
                if (loadedText == "")
                {
                    Debug.LogError("Empty model file.");
                }
                // remove this progress to let complete the total loading process
                totalProgress.singleProgress.Remove(objLoadingProgress);
                yield break;
            }
            //Debug.LogFormat("Parsing geometry data in {0}...", www.url);

            yield return ParseGeometryData(loadedText);
        }


        protected override IEnumerator LoadMaterialLibrary(string absolutePath)
        {
            string mtlPath;
            string basePath = GetDirName(absolutePath);
            if (absolutePath.Contains("//"))
            {
                int pos;
                // handle the special case of a PHP URL containing "...?...=model.obj"
                if (absolutePath.Contains("?"))
                {
                    // in this case try to get the library path reading until last "=".
                    pos = absolutePath.LastIndexOf('=');
                }
                else
                {
                    pos = absolutePath.LastIndexOf('/');
                }
                mtlPath = absolutePath.Remove(pos + 1) + mtlLib;
            }
            else
            {
                if(Path.IsPathRooted(mtlLib))
                {
                    mtlPath = "file:///" + mtlLib;
                }
                else
                {
                    mtlPath = "file:///" + basePath + mtlLib;
                }
            }
            yield return LoadOrDownloadText(mtlPath,false);
            if (loadedText == null)
            {
                mtlLib = Path.GetFileName(mtlLib);
                mtlPath = "file:///" + basePath + mtlLib;
                Debug.LogWarningFormat("Material library {0} loaded from the same directory as the OBJ file.\n", mtlLib);

                yield return LoadOrDownloadText(mtlPath);
            }

            if (loadedText != null)
            {
                //Debug.LogFormat("Parsing material library {0}...", loader.url);
                objLoadingProgress.message = "Parsing material library...";
                ParseMaterialData(loadedText);
            }

        }


        private void GetFaceIndicesByOneFaceLine(DataSet.FaceIndices[] faces, string[] p, bool isFaceIndexPlus)
        {
            if (isFaceIndexPlus)
            {
                for (int j = 1; j < p.Length; j++)
                {
                    string[] c = p[j].Trim().Split("/".ToCharArray());
                    DataSet.FaceIndices fi = new DataSet.FaceIndices();
                    // vertex
                    int vi = int.Parse(c[0]);
                    fi.vertIdx = vi - 1;
                    // uv
                    if (c.Length > 1 && c[1] != "")
                    {
                        int vu = int.Parse(c[1]);
                        fi.uvIdx = vu - 1;
                    }
                    // normal
                    if (c.Length > 2 && c[2] != "")
                    {
                        int vn = int.Parse(c[2]);
                        fi.normIdx = vn - 1;
                    }
                    else
                    {
                        fi.normIdx = -1;
                    }
                    faces[j - 1] = fi;
                }
            }
            else
            { // for minus index
                int vertexCount = dataSet.vertList.Count;
                int uvCount = dataSet.uvList.Count;
                for (int j = 1; j < p.Length; j++)
                {
                    string[] c = p[j].Trim().Split("/".ToCharArray());
                    DataSet.FaceIndices fi = new DataSet.FaceIndices();
                    // vertex
                    int vi = int.Parse(c[0]);
                    fi.vertIdx = vertexCount + vi;
                    // uv
                    if (c.Length > 1 && c[1] != "")
                    {
                        int vu = int.Parse(c[1]);
                        fi.uvIdx = uvCount + vu;
                    }
                    // normal
                    if (c.Length > 2 && c[2] != "")
                    {
                        int vn = int.Parse(c[2]);
                        fi.normIdx = vertexCount + vn;
                    }
                    else
                    {
                        fi.normIdx = -1;
                    }
                    faces[j - 1] = fi;
                }
            }
        }


        /// <summary>
        /// Convert coordinates according to import options.
        /// </summary>
        private Vector3 ConvertVec3(float x, float y, float z)
        {
            if (Scaling != 1f)
            {
                x *= Scaling;
                y *= Scaling;
                z *= Scaling;
            }
            if (ConvertVertAxis) return new Vector3(x, z, y);
            return new Vector3(x, y, -z);
        }


        /// <summary>
        /// Parse a string to get a floating point number using the invariant culture.
        /// </summary>
        /// <param name="floatString">String with the number to be parsed</param>
        /// <returns>The parsed floating point number.</returns>
        private float ParseFloat(string floatString)
        {
            return float.Parse(floatString, CultureInfo.InvariantCulture.NumberFormat);
        }


        /// <summary>
        /// Parse the OBJ file to extract geometry data.
        /// </summary>
        /// <param name="objDataText">OBJ file text</param>
        /// <returns>Execution is split into steps to not freeze the caller method.</returns>
        protected IEnumerator ParseGeometryData(string objDataText)
        {
            string[] lines = objDataText.Split("\n".ToCharArray());

            bool isFirstInGroup = true;
            bool isFaceIndexPlus = true;

            objLoadingProgress.message = "Parsing geometry data...";
            // store separators, used multiple times
            char[] separators = new char[] { ' ', '\t' };
            for (int i = 0; i < lines.Length; i++)
            {
                // update progress only sometimes
                if (i % 7000 == 0)
                {
                    objLoadingProgress.percentage = LOAD_PHASE_PERC * i / lines.Length;
                    yield return null;
                }

                string line = lines[i].Trim();

                if (line.Length > 0 && line[0] == '#')
                { // comment line
                    continue;
                }
                string[] p = line.Split(separators, StringSplitOptions.RemoveEmptyEntries);
                if (p.Length == 0)
                { // empty line
                    continue;
                }

                string parameters = null;
                if (line.Length > p[0].Length)
                {
                    parameters = line.Substring(p[0].Length + 1).Trim();
                }

                switch (p[0])
                {
                    case "o":
                        dataSet.AddObject(parameters);
                        isFirstInGroup = true;
                        break;
                    case "g":
                        isFirstInGroup = true;
                        dataSet.AddGroup(parameters);
                        break;
                    case "v":
                        dataSet.AddVertex(ConvertVec3(ParseFloat(p[1]), ParseFloat(p[2]), ParseFloat(p[3])));
                        if (p.Length >= 7)
                        {
                            // 7 for "v x y z r g b"
                            // 8 for "v x y z r g b w"
                            // w is the weight required for rational curves and surfaces. It is
                            // not required for non - rational curves and surfaces.If you do not
                            // specify a value for w, the default is 1.0. [http://paulbourke.net/dataformats/obj/]
                            dataSet.AddColor(new Color(ParseFloat(p[4]), ParseFloat(p[5]), ParseFloat(p[6]), 1f));
                        }
                        break;
                    case "vt":
                        dataSet.AddUV(new Vector2(ParseFloat(p[1]), ParseFloat(p[2])));
                        break;
                    case "vn":
                        dataSet.AddNormal(ConvertVec3(ParseFloat(p[1]), ParseFloat(p[2]), ParseFloat(p[3])));
                        break;
                    case "f":
                        {
                            int numVerts = p.Length - 1;
                            DataSet.FaceIndices[] face = new DataSet.FaceIndices[numVerts];
                            if (isFirstInGroup)
                            {
                                isFirstInGroup = false;
                                string[] c = p[1].Trim().Split("/".ToCharArray());
                                isFaceIndexPlus = (int.Parse(c[0]) >= 0);
                            }
                            GetFaceIndicesByOneFaceLine(face, p, isFaceIndexPlus);
                            if (numVerts == 3)
                            {
                                dataSet.AddFaceIndices(face[0]);
                                dataSet.AddFaceIndices(face[2]);
                                dataSet.AddFaceIndices(face[1]);
                            }
                            else
                            {
                                // Triangulate the polygon
                                // TODO: Texturing and lighting work better with a triangulation that maximizes triangles areas.
                                // TODO: the following true must be replaced to a proper option (disabled by default) as soon as a proper triangulation method is implemented.
                                Triangulator.Triangulate(dataSet, face);
                                // TODO: Maybe triangulation could be done in ObjectImporter instead.
                            }
                        }
                        break;
                    case "mtllib":
                        if (!string.IsNullOrEmpty(parameters))
                        {
                            mtlLib = parameters;
                        }
                        break;
                    case "usemtl":
                        if (!string.IsNullOrEmpty(parameters))
                        {
                            dataSet.AddMaterialName(DataSet.FixMaterialName(parameters));
                        }
                        break;
                    default:
                        Debug.LogWarning("OBJ element not supported: " + p[0]);
                        break;
                }
            }
            objLoadingProgress.percentage = LOAD_PHASE_PERC;
            //dataSet.PrintSummary();
        }


        /// <summary>
        /// Extract the material library (file) name from the OBJ file.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private string ParseMaterialLibName(string path)
        {
            string[] lines = Filesystem.ReadAllLines(path);

            objLoadingProgress.message = "Parsing geometry data...";

            for (int i = 0; i < lines.Length; i++)
            {
                string l = lines[i].Trim();

                if (l.StartsWith("mtllib"))
                {
                    return l.Substring("mtllib".Length).Trim();
                }
            }
            return null;
        }


        /// <summary>
        /// Check if a material library file is defined.
        /// </summary>
        protected override bool HasMaterialLibrary
        {
            get
            {
                return mtlLib != null;
            }
        }


        /// <summary>
        /// Parse the material library text to get material data.
        /// </summary>
        /// <param name="data">material library text (read from file)</param>
        private void ParseMaterialData(string data)
        {
            objLoadingProgress.message = "Parsing material data...";
            string[] lines = data.Split("\n".ToCharArray());
            materialData = new List<MaterialData>();
            ParseMaterialData(lines, materialData);
        }


        /// <summary>
        /// Parse the material library lines to get material data.
        /// </summary>
        /// <param name="lines">lines read from the material library file</param>
        /// <param name="mtlData">list of material data</param>
        private void ParseMaterialData(string[] lines, List<MaterialData> mtlData)
        {
            MaterialData current = new MaterialData();

            char[] separators = new char[] { ' ', '\t' };
            for (int i = 0; i < lines.Length; i++)
            {
                string line = lines[i].Trim();

                // remove comments
                if (line.IndexOf("#") != -1) line = line.Substring(0, line.IndexOf("#"));
                string[] p = line.Split(separators, StringSplitOptions.RemoveEmptyEntries);
                if (p.Length == 0 || string.IsNullOrEmpty(p[0])) continue;
                string parameters = null;
                if (line.Length > p[0].Length)
                {
                    parameters = line.Substring(p[0].Length + 1).Trim();
                }
                try
                {
                    switch (p[0])
                    {
                        case "newmtl":
                            current = new MaterialData();
                            current.materialName = DataSet.FixMaterialName(parameters);
                            mtlData.Add(current);
                            break;
                        case "Ka": // Ambient component (not supported)
                            current.ambientColor = StringsToColor(p);
                            break;
                        case "Kd": // Diffuse component
                            current.diffuseColor = StringsToColor(p);
                            break;
                        case "Ks": // Specular component
                            current.specularColor = StringsToColor(p);
                            break;
                        case "Ke": // Specular component
                            current.emissiveColor = StringsToColor(p);
                            break;
                        case "Ns": // Specular exponent --> shininess
                            current.shininess = ParseFloat(p[1]);
                            break;
                        case "d": // dissolve into the background (1=opaque, 0=transparent)
                            current.overallAlpha = p.Length > 1 && p[1] != "" ? ParseFloat(p[1]) : 1.0f;
                            break;
                        case "Tr": // Transparency
                            current.overallAlpha = p.Length > 1 && p[1] != "" ? 1.0f - ParseFloat(p[1]) : 1.0f;
                            break;
                        case "map_KD":
                        case "map_Kd": // Color texture, diffuse reflectivity
                            if (!string.IsNullOrEmpty(parameters))
                            {
                                current.diffuseTexPath = parameters;
                            }
                            break;
                        // TODO: different processing needed, options not supported
                        case "map_Ks": // specular reflectivity of the material
                        case "map_kS":
                        case "map_Ns": // Scalar texture for specular exponent
                            if (!string.IsNullOrEmpty(parameters))
                            {
                                current.specularTexPath = parameters;
                            }
                            break;
                        case "map_bump": // Bump map texture
                            if (!string.IsNullOrEmpty(parameters))
                            {
                                current.bumpTexPath = parameters;
                            }
                            break;
                        case "bump":
                            ParseBumpParameters(p, current);
                            break;
                        case "map_opacity":
                        case "map_d": // Scalar texture modulating the dissolve into the background
                            if (!string.IsNullOrEmpty(parameters))
                            {
                                current.opacityTexPath = parameters;
                            }
                            break;
                        case "illum": // Illumination model. 1 - diffuse, 2 - specular (not used)
                            current.illumType = int.Parse(p[1]);
                            break;
                        case "refl": // reflection map (replaced with Unity environment reflection)
                            if (!string.IsNullOrEmpty(parameters))
                            {
                                current.hasReflectionTex = true;
                            }
                            break;
                        case "map_Ka": // ambient reflectivity color texture
                        case "map_kA":
                            if (!string.IsNullOrEmpty(parameters))
                            {
                                Debug.Log("Map not supported:" + line);
                            }
                            break;
                        default:
                            Debug.Log("this line was not processed :" + line);
                            break;
                    }
                }
                catch (Exception e)
                {
                    Debug.LogErrorFormat("Error at line {0} in mtl file: {1}", i + 1, e);
                }
            }
        }


        /// <summary>
        /// Parse bump parameters.
        /// </summary>
        /// <param name="param">list of paramers</param>
        /// <param name="mtlData">material data to be updated</param>
        /// <remarks>Only the bump map texture path is used here.</remarks>
        /// <seealso cref="https://github.com/hammmm/unity-obj-loader"/>
        private void ParseBumpParameters(string[] param, MaterialData mtlData)
        {
            Regex regexNumber = new Regex(@"^[-+]?[0-9]*\.?[0-9]+$");

            var bumpParams = new Dictionary<string, BumpParamDef>();
            bumpParams.Add("bm", new BumpParamDef("bm", "string", 1, 1));
            bumpParams.Add("clamp", new BumpParamDef("clamp", "string", 1, 1));
            bumpParams.Add("blendu", new BumpParamDef("blendu", "string", 1, 1));
            bumpParams.Add("blendv", new BumpParamDef("blendv", "string", 1, 1));
            bumpParams.Add("imfchan", new BumpParamDef("imfchan", "string", 1, 1));
            bumpParams.Add("mm", new BumpParamDef("mm", "string", 1, 1));
            bumpParams.Add("o", new BumpParamDef("o", "number", 1, 3));
            bumpParams.Add("s", new BumpParamDef("s", "number", 1, 3));
            bumpParams.Add("t", new BumpParamDef("t", "number", 1, 3));
            bumpParams.Add("texres", new BumpParamDef("texres", "string", 1, 1));
            int pos = 1;
            string filename = null;
            while (pos < param.Length)
            {
                if (!param[pos].StartsWith("-"))
                {
                    filename = param[pos];
                    pos++;
                    continue;
                }
                // option processing
                string optionName = param[pos].Substring(1);
                pos++;
                if (!bumpParams.ContainsKey(optionName))
                {
                    continue;
                }
                BumpParamDef def = bumpParams[optionName];
                ArrayList args = new ArrayList();
                int i = 0;
                bool isOptionNotEnough = false;
                for (; i < def.valueNumMin; i++, pos++)
                {
                    if (pos >= param.Length)
                    {
                        isOptionNotEnough = true;
                        break;
                    }
                    if (def.valueType == "number")
                    {
                        Match match = regexNumber.Match(param[pos]);
                        if (!match.Success)
                        {
                            isOptionNotEnough = true;
                            break;
                        }
                    }
                    args.Add(param[pos]);
                }
                if (isOptionNotEnough)
                {
                    Debug.Log("bump variable value not enough for option:" + optionName + " of material:" + mtlData.materialName);
                    continue;
                }
                for (; i < def.valueNumMax && pos < param.Length; i++, pos++)
                {
                    if (def.valueType == "number")
                    {
                        Match match = regexNumber.Match(param[pos]);
                        if (!match.Success)
                        {
                            break;
                        }
                    }
                    args.Add(param[pos]);
                }
                // TODO: some processing of options
                Debug.Log("found option: " + optionName + " of material: " + mtlData.materialName + " args: " + string.Concat(args.ToArray()));
            }
            // set the file name, if found
            // TODO: other parsed parameters are not used for now
            if (filename != null)
            {
                mtlData.bumpTexPath = filename;
            }
        }


        private Color StringsToColor(string[] p)
        {
            return new Color(ParseFloat(p[1]), ParseFloat(p[2]), ParseFloat(p[3]));
        }


        private IEnumerator LoadOrDownloadText(string url, bool notifyErrors = true)
        {
            loadedText = null;

            var enumerable = Filesystem.DownloadUri(url, notifyErrors);

            yield return enumerable;

            if (enumerable.Current != null)
            {
                loadedText = (string)enumerable.Current;
            }
        }


        /// <summary>
        /// Bump parameter definition
        /// </summary>
        /// <remarks>Not really used for material definition, for now.</remarks>
        /// <see cref="https://github.com/hammmm/unity-obj-loader"/>
        private class BumpParamDef
        {
            public string optionName;
            public string valueType;
            public int valueNumMin;
            public int valueNumMax;
            public BumpParamDef(string name, string type, int numMin, int numMax)
            {
                optionName = name;
                valueType = type;
                valueNumMin = numMin;
                valueNumMax = numMax;
            }
        }
    }
}


================================================
FILE: Assets/AsImpL/Scripts/Loaders/LoaderObj.cs.meta
================================================
fileFormatVersion: 2
guid: 6693363d7ca36354bb03e6cf68c2faf5
timeCreated: 1455108182
licenseType: Free
MonoImporter:
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData: 
  assetBundleName: 
  assetBundleVariant: 


================================================
FILE: Assets/AsImpL/Scripts/Loaders/TextureLoader.cs
================================================
using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;

namespace AsImpL
{
    /// <summary>
    /// Class for loading textures files into Unity scene at run-time and in editor mode.
    /// </summary>
    /// <remarks>
    /// Derived from "Runtime OBJ Loader"
    /// (http://forum.unity3d.com/threads/free-runtime-obj-loader.365884/)
    /// and from "runtime .OBJ file loader for Unity3D"
    /// (https://github.com/hammmm/unity-obj-loader) and 
    /// (https://github.com/cmdr2/unity-remote-obj-loader)
    /// 
    /// </remarks>
    public class TextureLoader : MonoBehaviour
    {
        private static IFilesystem _filesystem = null;
        public static IFilesystem Filesystem
        {
            get
            {
                if (_filesystem == null)
                {
                    _filesystem = new FileFilesystem();
                }

                return _filesystem;
            }

            set
            {
                _filesystem = value;
            }
        }

        /// <summary>
        /// Load an image from a file into a Texture2D.
        /// </summary>
        /// <param name="url">URL of the texture image.</param>
        /// <returns>The loaded texture or null on error.</returns>
        public static Texture2D LoadTextureFromUrl(string url)
        {
            const string prefix = "file:///";
            if (url.StartsWith(prefix))
            {
                url = url.Substring(prefix.Length);
            }
            else
            {
                url = Path.GetFullPath(url);
            }
            return LoadTexture(url);
        }


        /// <summary>
        /// Load an image from a file into a Texture2D.
        /// </summary>
        /// <param name="fileName">file name of the image to load</param>
        /// <returns>The loaded texture or null on error.</returns>
        public static Texture2D LoadTexture(string fileName)
        {
            string ext = Path.GetExtension(fileName).ToLower();
            if (ext == ".png" || ext == ".jpg")
            {
                Texture2D t2d = new Texture2D(1, 1);
                t2d.LoadImage(Filesystem.ReadAllBytes(fileName));
                return t2d;
            }
            else if (ext == ".dds")
            {
                Texture2D returnTex = LoadDDSManual(fileName);
                return returnTex;
            }
            else if (ext == ".tga")
            {
                Texture2D returnTex = LoadTGA(fileName);
                return returnTex;
            }
            else
            {
                Debug.Log("texture not supported : " + fileName);
            }
            return null;
        }


        /// <summary>
        /// Load a TGA image from a file into a Texture2D.
        /// </summary>
        /// <param name="fileName">file name of the image to load</param>
        /// <returns>The loaded texture or null on error.</returns>
        public static Texture2D LoadTGA(string fileName)
        {
            using (var imageFile = Filesystem.OpenRead(fileName))
            {
                return LoadTGA(imageFile);
            }
        }


        /// <summary>
        /// Load a DDS image from a file into a Texture2D.
        /// </summary>
        /// <param name="ddsPath">file name of the image to load</param>
        /// <returns>The loaded texture or null on error.</retu
Download .txt
gitextract_wtwu_s1p/

├── .editorconfig
├── .gitattributes
├── .github/
│   └── ISSUE_TEMPLATE.md
├── .gitignore
├── Assets/
│   ├── AsImpL/
│   │   ├── Examples/
│   │   │   ├── 001_Import_SimpleTest.unity
│   │   │   ├── 001_Import_SimpleTest.unity.meta
│   │   │   ├── 002_Import_CustomImporter.unity
│   │   │   ├── 002_Import_CustomImporter.unity.meta
│   │   │   ├── 003_Import_URL_Test.unity
│   │   │   ├── 003_Import_URL_Test.unity.meta
│   │   │   ├── 004_Import_DestroyTest.unity
│   │   │   ├── 004_Import_DestroyTest.unity.meta
│   │   │   ├── Scripts/
│   │   │   │   ├── AsImpLSample.cs
│   │   │   │   ├── AsImpLSample.cs.meta
│   │   │   │   ├── CustomObjImporter.cs
│   │   │   │   ├── CustomObjImporter.cs.meta
│   │   │   │   ├── ImportDestroyTest.cs
│   │   │   │   ├── ImportDestroyTest.cs.meta
│   │   │   │   ├── Util/
│   │   │   │   │   ├── EditorLikeCameraController.cs
│   │   │   │   │   └── EditorLikeCameraController.cs.meta
│   │   │   │   └── Util.meta
│   │   │   └── Scripts.meta
│   │   ├── Examples.meta
│   │   ├── Resources/
│   │   │   ├── Materials/
│   │   │   │   ├── StandardCutout.mat
│   │   │   │   ├── StandardCutout.mat.meta
│   │   │   │   ├── StandardFade.mat
│   │   │   │   ├── StandardFade.mat.meta
│   │   │   │   ├── StandardOpaqueBump.mat
│   │   │   │   ├── StandardOpaqueBump.mat.meta
│   │   │   │   ├── StandardOpaqueMetallic.mat
│   │   │   │   ├── StandardOpaqueMetallic.mat.meta
│   │   │   │   ├── StandardTransparent.mat
│   │   │   │   ├── StandardTransparent.mat.meta
│   │   │   │   ├── UnlitTexture.mat
│   │   │   │   └── UnlitTexture.mat.meta
│   │   │   ├── Materials.meta
│   │   │   ├── Shaders/
│   │   │   │   ├── SimpleVertexColorsShader.shader
│   │   │   │   └── SimpleVertexColorsShader.shader.meta
│   │   │   ├── Shaders.meta
│   │   │   ├── Textures/
│   │   │   │   ├── diffuse.jpg.meta
│   │   │   │   ├── normalmap.png.meta
│   │   │   │   ├── opacity.png.meta
│   │   │   │   └── specular.png.meta
│   │   │   └── Textures.meta
│   │   ├── Resources.meta
│   │   ├── Scripts/
│   │   │   ├── Dataset/
│   │   │   │   ├── DataSet.cs
│   │   │   │   ├── DataSet.cs.meta
│   │   │   │   ├── IMaterialFactory.cs
│   │   │   │   ├── IMaterialFactory.cs.meta
│   │   │   │   ├── IShaderSelector.cs
│   │   │   │   ├── IShaderSelector.cs.meta
│   │   │   │   ├── MaterialData.cs
│   │   │   │   ├── MaterialData.cs.meta
│   │   │   │   ├── MaterialFactory.cs
│   │   │   │   ├── MaterialFactory.cs.meta
│   │   │   │   ├── ModelReferences.cs
│   │   │   │   ├── ModelReferences.cs.meta
│   │   │   │   ├── ModelUtil.cs
│   │   │   │   ├── ModelUtil.cs.meta
│   │   │   │   ├── ObjectBuilder.cs
│   │   │   │   ├── ObjectBuilder.cs.meta
│   │   │   │   ├── ShaderSelector.cs
│   │   │   │   ├── ShaderSelector.cs.meta
│   │   │   │   ├── Triangulator.cs
│   │   │   │   └── Triangulator.cs.meta
│   │   │   ├── Dataset.meta
│   │   │   ├── Editor/
│   │   │   │   ├── ObjImportWindow.cs
│   │   │   │   └── ObjImportWindow.cs.meta
│   │   │   ├── Editor.meta
│   │   │   ├── EditorUtil.cs
│   │   │   ├── EditorUtil.cs.meta
│   │   │   ├── IO/
│   │   │   │   ├── FileFilesystem.cs
│   │   │   │   ├── FileFilesystem.cs.meta
│   │   │   │   ├── IFilesystem.cs
│   │   │   │   └── IFilesystem.cs.meta
│   │   │   ├── IO.meta
│   │   │   ├── ImportOptions.cs
│   │   │   ├── ImportOptions.cs.meta
│   │   │   ├── Loaders/
│   │   │   │   ├── Loader.cs
│   │   │   │   ├── Loader.cs.meta
│   │   │   │   ├── LoaderObj.cs
│   │   │   │   ├── LoaderObj.cs.meta
│   │   │   │   ├── TextureLoader.cs
│   │   │   │   └── TextureLoader.cs.meta
│   │   │   ├── Loaders.meta
│   │   │   ├── LoadingProgress.cs
│   │   │   ├── LoadingProgress.cs.meta
│   │   │   ├── MathUtil/
│   │   │   │   ├── MathData/
│   │   │   │   │   ├── Triangle.cs
│   │   │   │   │   ├── Triangle.cs.meta
│   │   │   │   │   ├── Vertex.cs
│   │   │   │   │   └── Vertex.cs.meta
│   │   │   │   ├── MathData.meta
│   │   │   │   ├── MathUtility.cs
│   │   │   │   ├── MathUtility.cs.meta
│   │   │   │   ├── Triangulation.cs
│   │   │   │   └── Triangulation.cs.meta
│   │   │   ├── MathUtil.meta
│   │   │   ├── ModelImportInfo.cs
│   │   │   ├── ModelImportInfo.cs.meta
│   │   │   ├── MultiObjectImporter.cs
│   │   │   ├── MultiObjectImporter.cs.meta
│   │   │   ├── ObjectImporter.cs
│   │   │   ├── ObjectImporter.cs.meta
│   │   │   ├── ObjectImporterUI.cs
│   │   │   ├── ObjectImporterUI.cs.meta
│   │   │   ├── PathSettings.cs
│   │   │   └── PathSettings.cs.meta
│   │   └── Scripts.meta
│   └── AsImpL.meta
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Documentation/
│   └── AsImpL.chm
├── EXAMPLES.md
├── LICENSE.txt
├── ProjectSettings/
│   ├── AudioManager.asset
│   ├── ClusterInputManager.asset
│   ├── DynamicsManager.asset
│   ├── EditorBuildSettings.asset
│   ├── EditorSettings.asset
│   ├── GraphicsSettings.asset
│   ├── InputManager.asset
│   ├── NavMeshAreas.asset
│   ├── NetworkManager.asset
│   ├── Physics2DSettings.asset
│   ├── ProjectSettings.asset
│   ├── QualitySettings.asset
│   ├── TagManager.asset
│   ├── TimeManager.asset
│   ├── UnityAdsSettings.asset
│   └── UnityConnectSettings.asset
├── README.md
├── models/
│   ├── OBJ_test/
│   │   ├── README.txt
│   │   ├── objtest.mtl
│   │   ├── objtest_yup.obj
│   │   ├── objtest_zup.obj
│   │   ├── testBumpRefl.obj
│   │   ├── testDiffBump.obj
│   │   ├── testDiffOpacity.obj
│   │   ├── testRefl.obj
│   │   └── testTransp.obj
│   └── object_list_test.xml
└── package.json
Download .txt
SYMBOL INDEX (205 symbols across 32 files)

FILE: Assets/AsImpL/Examples/Scripts/AsImpLSample.cs
  class AsImpLSample (line 10) | public class AsImpLSample : MonoBehaviour
    method Awake (line 27) | private void Awake()
    method Start (line 38) | protected virtual void Start()
    method OnValidate (line 44) | private void OnValidate()

FILE: Assets/AsImpL/Examples/Scripts/CustomObjImporter.cs
  class CustomObjImporter (line 20) | public class CustomObjImporter : MultiObjectImporter
    method Awake (line 30) | private void Awake()
    method Start (line 36) | protected override void Start()
    method SetScaling (line 87) | public void SetScaling(float scl)
    method OnImportingComplete (line 95) | protected override void OnImportingComplete()
    method Save (line 102) | public void Save()
    method Reload (line 126) | public void Reload()
    method UpdateObject (line 150) | private void UpdateObject(GameObject gameObj, ModelImportInfo importInfo)
    method UpdateImportInfo (line 163) | private void UpdateImportInfo(ModelImportInfo importInfo, GameObject g...
    method UpdateObjectList (line 176) | private void UpdateObjectList()
    method UpdateScene (line 190) | private void UpdateScene()

FILE: Assets/AsImpL/Examples/Scripts/ImportDestroyTest.cs
  class ImportDestroyTest (line 13) | public class ImportDestroyTest : AsImpLSample
    method Start (line 19) | protected override void Start()
    method OnModelImported (line 26) | private void OnModelImported(GameObject obj, string objPath)
    method ReloadObject (line 31) | private IEnumerator ReloadObject(GameObject obj)

FILE: Assets/AsImpL/Examples/Scripts/Util/EditorLikeCameraController.cs
  class EditorLikeCameraController (line 7) | public class EditorLikeCameraController : MonoBehaviour
    method Awake (line 10) | void Awake()
    method Update (line 16) | void Update()

FILE: Assets/AsImpL/Scripts/Dataset/DataSet.cs
  class DataSet (line 11) | public class DataSet
    method GetFaceIndicesKey (line 75) | public static string GetFaceIndicesKey(FaceIndices fi)
    method FixMaterialName (line 86) | public static string FixMaterialName(string mtlName)
    method DataSet (line 103) | public DataSet()
    method AddObject (line 121) | public void AddObject(string objectName)
    method AddGroup (line 146) | public void AddGroup(string groupName)
    method AddMaterialName (line 169) | public void AddMaterialName(string matName)
    method AddVertex (line 181) | public void AddVertex(Vector3 vertex)
    method AddUV (line 191) | public void AddUV(Vector2 uv)
    method AddNormal (line 201) | public void AddNormal(Vector3 normal)
    method AddColor (line 211) | public void AddColor(Color color)
    method AddFaceIndices (line 222) | public void AddFaceIndices(FaceIndices faceIdx)
    method PrintSummary (line 237) | public void PrintSummary()
    type FaceIndices (line 258) | public struct FaceIndices
    class ObjectData (line 269) | public class ObjectData
      method ObjectData (line 276) | public ObjectData()
    class FaceGroupData (line 285) | public class FaceGroupData
      method FaceGroupData (line 290) | public FaceGroupData()

FILE: Assets/AsImpL/Scripts/Dataset/IMaterialFactory.cs
  type IMaterialFactory (line 8) | public interface IMaterialFactory
    method Create (line 10) | Material Create(string shaderName);

FILE: Assets/AsImpL/Scripts/Dataset/IShaderSelector.cs
  type IShaderSelector (line 6) | public interface IShaderSelector
    method Select (line 8) | string Select(MaterialData md, bool useUnlit, ModelUtil.MtlBlendMode b...

FILE: Assets/AsImpL/Scripts/Dataset/MaterialData.cs
  class MaterialData (line 11) | public class MaterialData

FILE: Assets/AsImpL/Scripts/Dataset/MaterialFactory.cs
  class MaterialFactory (line 8) | public class MaterialFactory : IMaterialFactory
    method Create (line 11) | public Material Create(string shaderName)

FILE: Assets/AsImpL/Scripts/Dataset/ModelReferences.cs
  class ModelReferences (line 16) | public class ModelReferences : MonoBehaviour
    method AddMesh (line 39) | public Mesh AddMesh(Mesh mesh)
    method AddMaterial (line 50) | public Material AddMaterial(Material material)
    method AddTexture (line 61) | public Texture2D AddTexture(Texture2D texture)
    method OnDestroy (line 71) | private void OnDestroy()

FILE: Assets/AsImpL/Scripts/Dataset/ModelUtil.cs
  class ModelUtil (line 10) | public class ModelUtil
    type MtlBlendMode (line 15) | public enum MtlBlendMode { OPAQUE, CUTOUT, FADE, TRANSPARENT }
    method SetupMaterialWithBlendMode (line 24) | public static void SetupMaterialWithBlendMode(Material mtl, MtlBlendMo...
    method ScanTransparentPixels (line 83) | public static bool ScanTransparentPixels(Texture2D texture, ref MtlBle...
    method DetectMtlBlendFadeOrCutout (line 126) | public static void DetectMtlBlendFadeOrCutout(float alpha, ref MtlBlen...
    method HeightToNormalMap (line 156) | public static Texture2D HeightToNormalMap(Texture2D bumpMap, float amo...
    method UpdateRendererMaterials (line 234) | public static void UpdateRendererMaterials(Renderer renderer)
    method WrapInt (line 250) | private static int WrapInt(int pos, int boundary)

FILE: Assets/AsImpL/Scripts/Dataset/ObjectBuilder.cs
  class ObjectBuilder (line 12) | public class ObjectBuilder
    method InitBuildMaterials (line 92) | public void InitBuildMaterials(List<MaterialData> materialData, bool h...
    method BuildMaterials (line 124) | public bool BuildMaterials(ProgressInfo info, ModelReferences modelRefs)
    method StartBuildObjectAsync (line 156) | public void StartBuildObjectAsync(DataSet dataSet, GameObject parentOb...
    method BuildObjectAsync (line 173) | public bool BuildObjectAsync(ref ProgressInfo info)
    method Solve (line 189) | public static void Solve(Mesh origMesh)
    method BuildMeshCollider (line 317) | public static void BuildMeshCollider(GameObject targetObject, bool con...
    method MeshSplitNeeded (line 345) | protected bool MeshSplitNeeded(DataSet.ObjectData objData)
    method BuildNextObject (line 373) | protected bool BuildNextObject(GameObject parentObj, Dictionary<string...
    method SetUpNewObject (line 420) | protected void SetUpNewObject(GameObject parentObj, DataSet.ObjectData...
    method BuildCurrentPart (line 452) | protected void BuildCurrentPart(DataSet.ObjectData objData, Dictionary...
    method ImportSubObject (line 545) | protected GameObject ImportSubObject(GameObject parentObj, DataSet.Obj...
    method BuildCurrentMesh (line 590) | protected void BuildCurrentMesh(DataSet.ObjectData objData, Dictionary...
    method BuildMesh (line 641) | protected Mesh BuildMesh(Renderer renderer, DataSet.ObjectData objData...
    method CreateMesh (line 668) | protected Mesh CreateMesh(DataSet.ObjectData objData, out Dictionary<s...
    method BuildSubMesh (line 774) | protected int BuildSubMesh(Mesh mesh, DataSet.ObjectData objData, Dict...
    method FinalizeMesh (line 807) | protected void FinalizeMesh(Mesh mesh, bool objDataHasNormals)
    method FinalizeObject (line 827) | protected void FinalizeObject(GameObject incompleteObj, Mesh mesh)
    method GetLibraryMaterial (line 851) | protected Material GetLibraryMaterial(Dictionary<string, Material> mat...
    method BuildMaterial (line 881) | protected Material BuildMaterial(MaterialData mtlData, ModelReferences...
    method Using32bitIndices (line 1158) | private bool Using32bitIndices()
    class ProgressInfo (line 1179) | public class ProgressInfo
    class BuildStatus (line 1188) | private class BuildStatus

FILE: Assets/AsImpL/Scripts/Dataset/ShaderSelector.cs
  class ShaderSelector (line 6) | public class ShaderSelector : IShaderSelector
    method ShaderSelector (line 10) | public ShaderSelector(string defaultShader = "Standard")
    method Select (line 16) | public string Select(MaterialData md, bool useUnlit, ModelUtil.MtlBlen...

FILE: Assets/AsImpL/Scripts/Dataset/Triangulator.cs
  class Triangulator (line 12) | public static class Triangulator
    method Triangulate (line 19) | public static void Triangulate(DataSet dataSet, DataSet.FaceIndices[] ...
    method FindPlaneNormal (line 55) | public static Vector3 FindPlaneNormal(DataSet dataSet, DataSet.FaceInd...

FILE: Assets/AsImpL/Scripts/Editor/ObjImportWindow.cs
  class ObjImportWindow (line 11) | public class ObjImportWindow : EditorWindow
    method ShowWindow (line 39) | [MenuItem("Assets/Import OBJ model... [AsImpL]", false, 20)]
    method Screenshot (line 46) | [MenuItem("Window/Capture screenshot [AsImpL]", false)]
    method SaveSettings (line 53) | private void SaveSettings()
    method ResetSettings (line 82) | private void ResetSettings()
    method OnEnable (line 155) | private void OnEnable()
    method OnGUI (line 161) | private void OnGUI()
    method Update (line 292) | private void Update()
    method OnInspectorUpdate (line 350) | private void OnInspectorUpdate()

FILE: Assets/AsImpL/Scripts/EditorUtil.cs
  class EditorUtil (line 9) | public class EditorUtil
    method CreateAssetFolder (line 16) | public static void CreateAssetFolder(string path, string folder)
    method AutoCaptureScreenshot (line 30) | public static void AutoCaptureScreenshot(string prefix)
    method SetTextureReadable (line 47) | public static void SetTextureReadable(string texAssetPath)
    method SaveAndReimportPngTexture (line 71) | public static void SaveAndReimportPngTexture(ref Texture2D texture, st...

FILE: Assets/AsImpL/Scripts/IO/FileFilesystem.cs
  method ReadAllBytes (line 13) | public byte[] ReadAllBytes(string path)
  method ReadAllLines (line 18) | public string[] ReadAllLines(string path)
  method OpenRead (line 23) | public FileStream OpenRead(string path)

FILE: Assets/AsImpL/Scripts/IO/IFilesystem.cs
  type IFilesystem (line 9) | public interface IFilesystem
    method ReadAllBytes (line 16) | byte[] ReadAllBytes(string path);
    method ReadAllLines (line 23) | string[] ReadAllLines(string path);
    method OpenRead (line 30) | FileStream OpenRead(string path);
    method DownloadUri (line 38) | IEnumerator DownloadUri(string uri, bool notifyErrors);
    method DownloadTexture (line 45) | IEnumerator DownloadTexture(string uri);

FILE: Assets/AsImpL/Scripts/ImportOptions.cs
  class ImportOptions (line 5) | [System.Serializable]

FILE: Assets/AsImpL/Scripts/Loaders/Loader.cs
  class Loader (line 20) | public abstract class Loader : MonoBehaviour
    method GetModelByPath (line 173) | public static GameObject GetModelByPath(string absolutePath)
    method Load (line 190) | public IEnumerator Load(string objName, string absolutePath, Transform...
    method ParseTexturePaths (line 276) | public abstract string[] ParseTexturePaths(string absolutePath);
    method LoadModelFile (line 283) | protected abstract IEnumerator LoadModelFile(string absolutePath);
    method LoadMaterialLibrary (line 290) | protected abstract IEnumerator LoadMaterialLibrary(string absolutePath);
    method Build (line 300) | protected IEnumerator Build(string absolutePath, string objName, Trans...
    method GetDirName (line 434) | protected string GetDirName(string absolutePath)
    method OnLoaded (line 454) | protected virtual void OnLoaded(GameObject obj, string absolutePath)
    method OnCreated (line 493) | protected virtual void OnCreated(GameObject obj, string absolutePath)
    method OnLoadFailed (line 512) | protected virtual void OnLoadFailed(string absolutePath)
    method LoadAssetTexture (line 527) | private Texture2D LoadAssetTexture(string texturePath)
    method GetTextureUrl (line 544) | private string GetTextureUrl(string basePath, string texturePath)
    method LoadMaterialTexture (line 560) | private IEnumerator LoadMaterialTexture(string basePath, string path)
    method LoadTexture (line 580) | private Texture2D LoadTexture(UnityWebRequest loader)
    method LoadTexture (line 582) | private Texture2D LoadTexture(WWW loader)
    type BuildStats (line 621) | protected struct BuildStats
    type Stats (line 629) | protected struct Stats

FILE: Assets/AsImpL/Scripts/Loaders/LoaderObj.cs
  class LoaderObj (line 38) | public class LoaderObj : Loader
    method ParseTexturePaths (line 49) | public override string[] ParseTexturePaths(string absolutePath)
    method LoadModelFile (line 88) | protected override IEnumerator LoadModelFile(string absolutePath)
    method LoadMaterialLibrary (line 110) | protected override IEnumerator LoadMaterialLibrary(string absolutePath)
    method GetFaceIndicesByOneFaceLine (line 160) | private void GetFaceIndicesByOneFaceLine(DataSet.FaceIndices[] faces, ...
    method ConvertVec3 (line 226) | private Vector3 ConvertVec3(float x, float y, float z)
    method ParseFloat (line 244) | private float ParseFloat(string floatString)
    method ParseGeometryData (line 255) | protected IEnumerator ParseGeometryData(string objDataText)
    method ParseMaterialLibName (line 374) | private string ParseMaterialLibName(string path)
    method ParseMaterialData (line 409) | private void ParseMaterialData(string data)
    method ParseMaterialData (line 423) | private void ParseMaterialData(string[] lines, List<MaterialData> mtlD...
    method ParseBumpParameters (line 539) | private void ParseBumpParameters(string[] param, MaterialData mtlData)
    method StringsToColor (line 622) | private Color StringsToColor(string[] p)
    method LoadOrDownloadText (line 628) | private IEnumerator LoadOrDownloadText(string url, bool notifyErrors =...
    class BumpParamDef (line 648) | private class BumpParamDef
      method BumpParamDef (line 654) | public BumpParamDef(string name, string type, int numMin, int numMax)

FILE: Assets/AsImpL/Scripts/Loaders/TextureLoader.cs
  class TextureLoader (line 20) | public class TextureLoader : MonoBehaviour
    method LoadTextureFromUrl (line 46) | public static Texture2D LoadTextureFromUrl(string url)
    method LoadTexture (line 66) | public static Texture2D LoadTexture(string fileName)
    method LoadTGA (line 98) | public static Texture2D LoadTGA(string fileName)
    method LoadDDSManual (line 112) | public static Texture2D LoadDDSManual(string ddsPath)
    method LoadTGA (line 168) | public static Texture2D LoadTGA(Stream TGAStream)
    method LoadTgaHeader (line 247) | private static TgaHeader LoadTgaHeader(BinaryReader r)
    class TgaHeader (line 289) | private class TgaHeader

FILE: Assets/AsImpL/Scripts/LoadingProgress.cs
  class SingleLoadingProgress (line 8) | public class SingleLoadingProgress
  class LoadingProgress (line 23) | public class LoadingProgress

FILE: Assets/AsImpL/Scripts/MathUtil/MathData/Triangle.cs
  class Triangle (line 7) | public class Triangle
    method Triangle (line 13) | public Triangle(Vertex v1, Vertex v2, Vertex v3)

FILE: Assets/AsImpL/Scripts/MathUtil/MathData/Vertex.cs
  class Vertex (line 9) | public class Vertex
    method Vertex (line 82) | public Vertex(int originalIndex, Vector3 position)
    method GetPosOnPlane (line 94) | public Vector2 GetPosOnPlane(Vector3 planeNormal)
    method ComputeTriangleArea (line 106) | private void ComputeTriangleArea()

FILE: Assets/AsImpL/Scripts/MathUtil/MathUtility.cs
  class MathUtility (line 8) | public static class MathUtility
    method ClampListIndex (line 20) | public static int ClampListIndex(int index, int listSize)
    method IsPointInTriangle (line 42) | public static bool IsPointInTriangle(Vector2 p1, Vector2 p2, Vector2 p...
    method IsTriangleOrientedClockwise (line 76) | public static bool IsTriangleOrientedClockwise(Vector2 v1, Vector2 v2,...
    method ComputeNormal (line 93) | public static Vector3 ComputeNormal(Vector3 vert, Vector3 vNext, Vecto...

FILE: Assets/AsImpL/Scripts/MathUtil/Triangulation.cs
  class Triangulation (line 11) | public static class Triangulation
    method TriangulateConvexPolygon (line 19) | public static List<Triangle> TriangulateConvexPolygon(List<Vertex> ver...
    method TriangulateByEarClipping (line 66) | public static List<Triangle> TriangulateByEarClipping(List<Vertex> ori...
    method ClipTriangle (line 121) | public static Triangle ClipTriangle(Vertex vertex, List<Vertex> vertices)
    method ClipEar (line 140) | private static Triangle ClipEar(Vertex earVertex, List<Vertex> earVert...
    method FindMaxAreaEarVertex (line 177) | private static Vertex FindMaxAreaEarVertex(List<Vertex> earVertices)
    method FindEarVertices (line 191) | private static List<Vertex> FindEarVertices(List<Vertex> vertices, Vec...
    method IsVertexReflex (line 209) | private static bool IsVertexReflex(Vertex v, Vector3 vNormal)
    method IsVertexEar (line 221) | private static bool IsVertexEar(Vertex v, List<Vertex> vertices, Vecto...

FILE: Assets/AsImpL/Scripts/ModelImportInfo.cs
  class ModelImportInfo (line 8) | [System.Serializable]
    method ModelImportInfo (line 23) | public ModelImportInfo()

FILE: Assets/AsImpL/Scripts/MultiObjectImporter.cs
  class MultiObjectImporter (line 11) | public class MultiObjectImporter : ObjectImporter
    method ImportModelListAsync (line 37) | public void ImportModelListAsync(ModelImportInfo[] modelsInfo)
    method Start (line 69) | protected virtual void Start()

FILE: Assets/AsImpL/Scripts/ObjectImporter.cs
  class ObjectImporter (line 16) | public class ObjectImporter : MonoBehaviour
    type ImportPhase (line 72) | private enum ImportPhase { Idle, TextureImport, ObjLoad, AssetBuild, D...
    method ImportFile (line 169) | public void ImportFile(string absolutePath, Transform parentObject, Im...
    method ImportFileAsync (line 182) | private IEnumerator ImportFileAsync(string absolutePath, Transform par...
    method CreateLoader (line 333) | private Loader CreateLoader(string absolutePath)
    method ImportModelAsync (line 381) | public void ImportModelAsync(string objName, string filePath, Transfor...
    method UpdateStatus (line 417) | public virtual void UpdateStatus()
    method Update (line 439) | protected virtual void Update()
    method OnImportingComplete (line 448) | protected virtual void OnImportingComplete()
    method OnModelCreated (line 460) | protected virtual void OnModelCreated(GameObject obj, string absoluteP...
    method OnImported (line 472) | protected virtual void OnImported(GameObject obj, string absolutePath)
    method OnImportError (line 484) | protected virtual void OnImportError(string absolutePath)

FILE: Assets/AsImpL/Scripts/ObjectImporterUI.cs
  class ObjectImporterUI (line 9) | [RequireComponent(typeof(ObjectImporter))]
    method Awake (line 24) | private void Awake()
    method OnEnable (line 44) | private void OnEnable()
    method OnDisable (line 51) | private void OnDisable()
    method Update (line 58) | private void Update()
    method OnImportStart (line 128) | private void OnImportStart()
    method OnImportComplete (line 147) | private void OnImportComplete()

FILE: Assets/AsImpL/Scripts/PathSettings.cs
  type RootPathEnum (line 7) | public enum RootPathEnum
  class PathSettings (line 17) | public class PathSettings : MonoBehaviour
    method FindPathComponent (line 58) | public static PathSettings FindPathComponent(GameObject obj)
    method FullPath (line 73) | public string FullPath(string path)
Condensed preview — 142 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,657K chars).
[
  {
    "path": ".editorconfig",
    "chars": 181,
    "preview": "; Used by the 'EditorConfig' VS plugin\n; See http://editorconfig.org\n\n; Use tabs preference set to 2 spaces per tab.\n[*."
  },
  {
    "path": ".gitattributes",
    "chars": 105,
    "preview": "# .gitattributes\n\n# Treat them as binary files for GitMerge\n*.unity binary\n*.prefab binary\n*.asset binary"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 1930,
    "preview": "  > **WARNING:** Any issue that does not follow the below template could be closed and not re-opened until the template "
  },
  {
    "path": ".gitignore",
    "chars": 411,
    "preview": "/[Ll]ibrary/\n/[Tt]emp/\n/Docs/\n/[Aa]ssets/[Aa]sset[Ss]tore[Tt]ools*\n/[Aa]ssets/[Pp]lugins*\n\n\n# Autogenerated VS/MD soluti"
  },
  {
    "path": "Assets/AsImpL/Examples/001_Import_SimpleTest.unity.meta",
    "chars": 175,
    "preview": "fileFormatVersion: 2\nguid: 451f9a57a3bcde1459f722853aa9e942\ntimeCreated: 1488539917\nlicenseType: Free\nDefaultImporter:\n "
  },
  {
    "path": "Assets/AsImpL/Examples/002_Import_CustomImporter.unity.meta",
    "chars": 175,
    "preview": "fileFormatVersion: 2\nguid: 431088c5d11fb6149baa2652870e9a37\ntimeCreated: 1455004990\nlicenseType: Free\nDefaultImporter:\n "
  },
  {
    "path": "Assets/AsImpL/Examples/003_Import_URL_Test.unity.meta",
    "chars": 175,
    "preview": "fileFormatVersion: 2\nguid: d5954e0fc8f8fac4682e7b99da510760\ntimeCreated: 1511337825\nlicenseType: Free\nDefaultImporter:\n "
  },
  {
    "path": "Assets/AsImpL/Examples/004_Import_DestroyTest.unity.meta",
    "chars": 175,
    "preview": "fileFormatVersion: 2\nguid: deac6f02203a0384d918df133c20a6c7\ntimeCreated: 1645622189\nlicenseType: Free\nDefaultImporter:\n "
  },
  {
    "path": "Assets/AsImpL/Examples/Scripts/AsImpLSample.cs",
    "chars": 1414,
    "preview": "using UnityEngine;\n\nnamespace AsImpL\n{\n    namespace Examples\n    {\n        /// <summary>\n        /// Demonstrate how t"
  },
  {
    "path": "Assets/AsImpL/Examples/Scripts/AsImpLSample.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: bee2f07bf5338dd42aaf5fc5283c1a66\ntimeCreated: 1488532022\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Examples/Scripts/CustomObjImporter.cs",
    "chars": 7923,
    "preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Xml;\nusing System.Text;\nusing System.Xml."
  },
  {
    "path": "Assets/AsImpL/Examples/Scripts/CustomObjImporter.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: 1aaecb2e4740ee44eab58edee766ade6\ntimeCreated: 1452761617\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Examples/Scripts/ImportDestroyTest.cs",
    "chars": 1203,
    "preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace AsImpL\n{\n    na"
  },
  {
    "path": "Assets/AsImpL/Examples/Scripts/ImportDestroyTest.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: a4f0318c2c384b14ca0671fa133f70fa\ntimeCreated: 1645622247\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Examples/Scripts/Util/EditorLikeCameraController.cs",
    "chars": 1287,
    "preview": "using UnityEngine;\n\nnamespace AsImpL\n{\n    namespace Examples\n    {\n        public class EditorLikeCameraController : M"
  },
  {
    "path": "Assets/AsImpL/Examples/Scripts/Util/EditorLikeCameraController.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: c7c40d4a6f6f5aa45a056cfbe4301b66\ntimeCreated: 1478530910\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Examples/Scripts/Util.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: 22a5be0aa0dd0e54a80d091fe3322f33\nfolderAsset: yes\ntimeCreated: 1488543190\nlicenseType: Free\nD"
  },
  {
    "path": "Assets/AsImpL/Examples/Scripts.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: 8a68e30fc3d54dd47ae5f6017cf909d0\nfolderAsset: yes\ntimeCreated: 1452774378\nlicenseType: Free\nD"
  },
  {
    "path": "Assets/AsImpL/Examples.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: 77617cdd806530c47a717d997786c6ba\nfolderAsset: yes\ntimeCreated: 1486633078\nlicenseType: Free\nD"
  },
  {
    "path": "Assets/AsImpL/Resources/Materials/StandardCutout.mat.meta",
    "chars": 180,
    "preview": "fileFormatVersion: 2\nguid: ce02b9c55bb8b524aab575e0b3e047a5\ntimeCreated: 1455546091\nlicenseType: Free\nNativeFormatImport"
  },
  {
    "path": "Assets/AsImpL/Resources/Materials/StandardFade.mat.meta",
    "chars": 180,
    "preview": "fileFormatVersion: 2\nguid: d553ada60d81dd0488389607fb6f3d35\ntimeCreated: 1455637853\nlicenseType: Free\nNativeFormatImport"
  },
  {
    "path": "Assets/AsImpL/Resources/Materials/StandardOpaqueBump.mat.meta",
    "chars": 180,
    "preview": "fileFormatVersion: 2\nguid: e83baad023334524d9f56155b1c433b9\ntimeCreated: 1455538553\nlicenseType: Free\nNativeFormatImport"
  },
  {
    "path": "Assets/AsImpL/Resources/Materials/StandardOpaqueMetallic.mat.meta",
    "chars": 180,
    "preview": "fileFormatVersion: 2\nguid: 26497679857597f4d82243edd29acadf\ntimeCreated: 1488550076\nlicenseType: Free\nNativeFormatImport"
  },
  {
    "path": "Assets/AsImpL/Resources/Materials/StandardTransparent.mat.meta",
    "chars": 180,
    "preview": "fileFormatVersion: 2\nguid: b29f2c52b07fbca4cb8d84df828b853e\ntimeCreated: 1455538582\nlicenseType: Free\nNativeFormatImport"
  },
  {
    "path": "Assets/AsImpL/Resources/Materials/UnlitTexture.mat.meta",
    "chars": 180,
    "preview": "fileFormatVersion: 2\nguid: 098032ac46e964e46875663fcdeacddd\ntimeCreated: 1548771631\nlicenseType: Free\nNativeFormatImport"
  },
  {
    "path": "Assets/AsImpL/Resources/Materials.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: 774dec663515133459e48baaf3034985\nfolderAsset: yes\ntimeCreated: 1550227278\nlicenseType: Free\nD"
  },
  {
    "path": "Assets/AsImpL/Resources/Shaders/SimpleVertexColorsShader.shader",
    "chars": 465,
    "preview": "// Simple Vertex Colors shader, used when only vertex colors are available\n\nShader \"Unlit/Simple Vertex Colors Shader\" {"
  },
  {
    "path": "Assets/AsImpL/Resources/Shaders/SimpleVertexColorsShader.shader.meta",
    "chars": 196,
    "preview": "fileFormatVersion: 2\nguid: 93f01d2146d2cee4da1df042a12543cb\ntimeCreated: 1512565342\nlicenseType: Free\nShaderImporter:\n  "
  },
  {
    "path": "Assets/AsImpL/Resources/Shaders.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: 82adea7a26b85af4ca881ba138b78298\nfolderAsset: yes\ntimeCreated: 1550227289\nlicenseType: Free\nD"
  },
  {
    "path": "Assets/AsImpL/Resources/Textures/diffuse.jpg.meta",
    "chars": 1475,
    "preview": "fileFormatVersion: 2\nguid: eead99b9b56006e4a9d7fb98b7a9886f\ntimeCreated: 1488550057\nlicenseType: Free\nTextureImporter:\n "
  },
  {
    "path": "Assets/AsImpL/Resources/Textures/normalmap.png.meta",
    "chars": 1475,
    "preview": "fileFormatVersion: 2\nguid: a0b134f9c1c11674687c93065fb2f07e\ntimeCreated: 1488550559\nlicenseType: Free\nTextureImporter:\n "
  },
  {
    "path": "Assets/AsImpL/Resources/Textures/opacity.png.meta",
    "chars": 1875,
    "preview": "fileFormatVersion: 2\nguid: 437784474ac4cf247bdc2c060fb8beec\ntimeCreated: 1488550526\nlicenseType: Free\nTextureImporter:\n "
  },
  {
    "path": "Assets/AsImpL/Resources/Textures/specular.png.meta",
    "chars": 1475,
    "preview": "fileFormatVersion: 2\nguid: 554f46dfdb7e37049aae3530dfd2913c\ntimeCreated: 1488550057\nlicenseType: Free\nTextureImporter:\n "
  },
  {
    "path": "Assets/AsImpL/Resources/Textures.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: b082fccb83cdc744c88032b4462ae698\nfolderAsset: yes\ntimeCreated: 1550227267\nlicenseType: Free\nD"
  },
  {
    "path": "Assets/AsImpL/Resources.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: 5677e9ac29b1e154f91a00612aacf1e8\nfolderAsset: yes\ntimeCreated: 1455020463\nlicenseType: Free\nD"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/DataSet.cs",
    "chars": 8974,
    "preview": "using UnityEngine;\nusing System.Collections.Generic;\n\nnamespace AsImpL\n{\n    /// <summary>\n    /// Data set for storing"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/DataSet.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: 41cb908b519c6d441a81eccaf9cadb02\ntimeCreated: 1487838131\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/IMaterialFactory.cs",
    "chars": 225,
    "preview": "using UnityEngine;\n\nnamespace AsImpL\n{\n    /// <summary>\n    /// Interface for classes that create materials.\n    /// <"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/IMaterialFactory.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 72c40b3bf79821f18983ae2c8d50c71d\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/IShaderSelector.cs",
    "chars": 284,
    "preview": "namespace AsImpL\n{\n    /// <summary>\n    /// Interface for classes that select the shader to use based on the material "
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/IShaderSelector.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 6d7bb6a6dd153df4bbe3388fccaa2593\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/MaterialData.cs",
    "chars": 1035,
    "preview": "using UnityEngine;\n\nnamespace AsImpL\n{\n    /// <summary>\n    /// Material data\n    /// </summary>\n    /// <remarks>This"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/MaterialData.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: dae7bec6fd5a92c42b9c46811163821e\ntimeCreated: 1487922714\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/MaterialFactory.cs",
    "chars": 389,
    "preview": "using UnityEngine;\n\nnamespace AsImpL\n{\n    /// <summary>\n    /// Implementation of IMaterialFactory that creates a mate"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/MaterialFactory.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 4aabc90e9be8e4b60b751f8f3ffd299c\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/ModelReferences.cs",
    "chars": 2770,
    "preview": "using System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\n#if UNITY_2018_1_OR_NEWER\nusing Unity.C"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/ModelReferences.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: 6c1f8e4b5a810a7429623b3c0afbdbbc\ntimeCreated: 1645617895\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/ModelUtil.cs",
    "chars": 10327,
    "preview": "using System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace AsImpL\n{\n    /// <summary>\n  "
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/ModelUtil.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: d645847b11a55f649ac02376e498bc4a\ntimeCreated: 1488373594\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/ObjectBuilder.cs",
    "chars": 49000,
    "preview": "using System.Collections.Generic;\nusing UnityEngine;\n#if UNITY_EDITOR\nusing UnityEditor;\n#endif\n\nnamespace AsImpL\n{\n   "
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/ObjectBuilder.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: 5d3b8da2516ecbd45a3510f7b70c877c\ntimeCreated: 1487834182\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/ShaderSelector.cs",
    "chars": 1233,
    "preview": "namespace AsImpL\n{\n    /// <summary>\n    /// Default implementation of IShaderSelector using predefined shaders.\n    //"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/ShaderSelector.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 73f70be058a983bdfb31daa3caad5069\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/Triangulator.cs",
    "chars": 3236,
    "preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing AsImpL.MathUtil;\n\nna"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset/Triangulator.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: 9ade097d341a67c4ab7ace3b1b12badd\ntimeCreated: 1547202713\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/Dataset.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: c9c1191ef9829594988154266262f765\nfolderAsset: yes\ntimeCreated: 1486633140\nlicenseType: Free\nD"
  },
  {
    "path": "Assets/AsImpL/Scripts/Editor/ObjImportWindow.cs",
    "chars": 15087,
    "preview": "using System.IO;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace AsImpL\n{\n    /// <summary>\n    /// Editor window for "
  },
  {
    "path": "Assets/AsImpL/Scripts/Editor/ObjImportWindow.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: 7edf263ef720bd04a94de49c8b447803\ntimeCreated: 1486545119\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/Editor.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: 09c5fcb0a17ffac489974fabba22e67d\nfolderAsset: yes\ntimeCreated: 1486633204\nlicenseType: Free\nD"
  },
  {
    "path": "Assets/AsImpL/Scripts/EditorUtil.cs",
    "chars": 4199,
    "preview": "#if UNITY_EDITOR\nusing System;\nusing System.IO;\nusing UnityEngine;\nusing UnityEditor;\n\nnamespace AsImpL\n{\n    public cl"
  },
  {
    "path": "Assets/AsImpL/Scripts/EditorUtil.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: dda14eb2e4479a44d88bb9c9466c1eef\ntimeCreated: 1488362452\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/IO/FileFilesystem.cs",
    "chars": 3969,
    "preview": "using System.Collections;\nusing System.IO;\nusing UnityEngine;\nusing UnityEngine.Networking;\n\nnamespace AsImpL\n{\n    /// "
  },
  {
    "path": "Assets/AsImpL/Scripts/IO/FileFilesystem.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 56918d1d8d26c6b488ec48ff28fe0dd7\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "Assets/AsImpL/Scripts/IO/IFilesystem.cs",
    "chars": 1535,
    "preview": "using System.Collections;\nusing System.IO;\n\nnamespace AsImpL\n{\n    /// <summary>\n    /// Interface for classes that acce"
  },
  {
    "path": "Assets/AsImpL/Scripts/IO/IFilesystem.cs.meta",
    "chars": 243,
    "preview": "fileFormatVersion: 2\nguid: 79a86b82a4f3ce7429ef221b36a9669e\nMonoImporter:\n  externalObjects: {}\n  serializedVersion: 2\n "
  },
  {
    "path": "Assets/AsImpL/Scripts/IO.meta",
    "chars": 172,
    "preview": "fileFormatVersion: 2\nguid: b4f2254e567d40540b17ed7bb78df22a\nfolderAsset: yes\nDefaultImporter:\n  externalObjects: {}\n  us"
  },
  {
    "path": "Assets/AsImpL/Scripts/ImportOptions.cs",
    "chars": 2400,
    "preview": "using UnityEngine;\n\nnamespace AsImpL\n{\n    [System.Serializable]\n    /// <summary>\n    /// Options to define how the mo"
  },
  {
    "path": "Assets/AsImpL/Scripts/ImportOptions.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: cb0228fe32d671f4e9d1e444c02da369\ntimeCreated: 1488270546\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/Loaders/Loader.cs",
    "chars": 23356,
    "preview": "using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.IO;\nusing UnityEngine;\nusing Uni"
  },
  {
    "path": "Assets/AsImpL/Scripts/Loaders/Loader.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: e11055a82efa5854bb71067ff3835d61\ntimeCreated: 1487939407\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/Loaders/LoaderObj.cs",
    "chars": 26872,
    "preview": "using UnityEngine;\nusing UnityEngine.Networking;\nusing System;\nusing System.Collections;\nusing System.Collections.Gener"
  },
  {
    "path": "Assets/AsImpL/Scripts/Loaders/LoaderObj.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: 6693363d7ca36354bb03e6cf68c2faf5\ntimeCreated: 1455108182\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/Loaders/TextureLoader.cs",
    "chars": 11469,
    "preview": "using System;\nusing System.Collections;\nusing System.IO;\nusing UnityEngine;\nusing UnityEngine.Networking;\n\nnamespace As"
  },
  {
    "path": "Assets/AsImpL/Scripts/Loaders/TextureLoader.cs.meta",
    "chars": 264,
    "preview": "fileFormatVersion: 2\nguid: cf60eb52e6d9f9c4c9d2e3c3a481459d\ntimeCreated: 1446890190\nlicenseType: Store\nMonoImporter:\n  s"
  },
  {
    "path": "Assets/AsImpL/Scripts/Loaders.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: 2944b8bb7a23b684da28f5427c07cc6d\nfolderAsset: yes\ntimeCreated: 1487834203\nlicenseType: Free\nD"
  },
  {
    "path": "Assets/AsImpL/Scripts/LoadingProgress.cs",
    "chars": 816,
    "preview": "using System.Collections.Generic;\n\nnamespace AsImpL\n{\n    /// <summary>\n    /// Loading progress information for a sing"
  },
  {
    "path": "Assets/AsImpL/Scripts/LoadingProgress.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: e11296a025dad7a45a38565d8a88ed91\ntimeCreated: 1487944040\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/MathUtil/MathData/Triangle.cs",
    "chars": 407,
    "preview": "namespace AsImpL.MathUtil\n{\n    /// <summary>\n    /// Triangle data structure.\n    /// </summary>\n    /// <seealso cref="
  },
  {
    "path": "Assets/AsImpL/Scripts/MathUtil/MathData/Triangle.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: 871a01cb55a1a3145ab72e57f55ce522\ntimeCreated: 1547458028\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/MathUtil/MathData/Vertex.cs",
    "chars": 3234,
    "preview": "using UnityEngine;\n\nnamespace AsImpL.MathUtil\n{\n    /// <summary>\n    /// Vertex structure used for triangulation.\n    /"
  },
  {
    "path": "Assets/AsImpL/Scripts/MathUtil/MathData/Vertex.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: a2abf08a23d9a2849b53c1c3dfdaa95d\ntimeCreated: 1547458028\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/MathUtil/MathData.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: ed1af689809ca144ebf52882176be40c\nfolderAsset: yes\ntimeCreated: 1547458027\nlicenseType: Free\nD"
  },
  {
    "path": "Assets/AsImpL/Scripts/MathUtil/MathUtility.cs",
    "chars": 3969,
    "preview": "using UnityEngine;\n\nnamespace AsImpL.MathUtil\n{\n    /// <summary>\n    /// Collection of useful mathematical methods.\n   "
  },
  {
    "path": "Assets/AsImpL/Scripts/MathUtil/MathUtility.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: a94cf84888e51204098bc64bc9fb8b68\ntimeCreated: 1547458028\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/MathUtil/Triangulation.cs",
    "chars": 9888,
    "preview": "using System.Collections.Generic;\nusing UnityEngine;\n\n\n/// <summary>\n/// Mathematical utility algorithms and related da"
  },
  {
    "path": "Assets/AsImpL/Scripts/MathUtil/Triangulation.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: 789435ba45b926d4c9c8adc294c4948b\ntimeCreated: 1547458028\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/MathUtil.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: b096756713587b241a564c32807fd3b8\nfolderAsset: yes\ntimeCreated: 1547456442\nlicenseType: Free\nD"
  },
  {
    "path": "Assets/AsImpL/Scripts/ModelImportInfo.cs",
    "chars": 654,
    "preview": "using UnityEngine;\n\nnamespace AsImpL\n{\n    /// <summary>\n    /// Model import settings, used for batch importing.\n    /"
  },
  {
    "path": "Assets/AsImpL/Scripts/ModelImportInfo.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: e9cf58c26a5958543871b670fe0d3717\ntimeCreated: 1455182724\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/MultiObjectImporter.cs",
    "chars": 2355,
    "preview": "using System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.UI;\n\nnamespace AsImpL\n"
  },
  {
    "path": "Assets/AsImpL/Scripts/MultiObjectImporter.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: fe360ae915fadfd468fbdb331dc84469\ntimeCreated: 1550227987\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/ObjectImporter.cs",
    "chars": 18274,
    "preview": "using System;\nusing System.IO;\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n#if UNITY"
  },
  {
    "path": "Assets/AsImpL/Scripts/ObjectImporter.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: 7aa7bdf849241b242afe32648ecd25c6\ntimeCreated: 1486627093\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/ObjectImporterUI.cs",
    "chars": 5344,
    "preview": "using UnityEngine;\nusing UnityEngine.UI;\n\nnamespace AsImpL\n{\n    /// <summary>\n    /// UI controller for <see cref=\"Obj"
  },
  {
    "path": "Assets/AsImpL/Scripts/ObjectImporterUI.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: 98ad2e3a9b1ab434ab6c6fd1ae74cda6\ntimeCreated: 1486637991\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts/PathSettings.cs",
    "chars": 2237,
    "preview": "using System.IO;\nusing System.Collections.Generic;\nusing UnityEngine;\n\nnamespace AsImpL\n{\n    public enum RootPathEnum\n"
  },
  {
    "path": "Assets/AsImpL/Scripts/PathSettings.cs.meta",
    "chars": 263,
    "preview": "fileFormatVersion: 2\nguid: 3e579ad933bbf124a947f0795cef45f6\ntimeCreated: 1550479872\nlicenseType: Free\nMonoImporter:\n  se"
  },
  {
    "path": "Assets/AsImpL/Scripts.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: 79f97e8a78566aa45864e694c568b081\nfolderAsset: yes\ntimeCreated: 1486632922\nlicenseType: Free\nD"
  },
  {
    "path": "Assets/AsImpL.meta",
    "chars": 192,
    "preview": "fileFormatVersion: 2\nguid: 8687f5d8b1856df4a888c82881dedada\nfolderAsset: yes\ntimeCreated: 1452761486\nlicenseType: Free\nD"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3215,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 12503,
    "preview": "# Contributing\n\nHere you find some guidelines for your contributions (this document is inspired by \n[these guidelines](h"
  },
  {
    "path": "EXAMPLES.md",
    "chars": 2829,
    "preview": "# Examples\n\nExamples work in Unity Editor, to make them work as standalone builds you must copy the `models` folder (wit"
  },
  {
    "path": "LICENSE.txt",
    "chars": 1088,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2018 Giovanni Paolo Viganò\n\nPermission is hereby granted, free of charge, to any pe"
  },
  {
    "path": "ProjectSettings/AudioManager.asset",
    "chars": 328,
    "preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!11 &1\nAudioManager:\n  m_ObjectHideFlags: 0\n  m_Volume: 1\n  Rolloff Scale"
  },
  {
    "path": "ProjectSettings/ClusterInputManager.asset",
    "chars": 114,
    "preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!236 &1\nClusterInputManager:\n  m_ObjectHideFlags: 0\n  m_Inputs: []\n"
  },
  {
    "path": "ProjectSettings/DynamicsManager.asset",
    "chars": 715,
    "preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!55 &1\nPhysicsManager:\n  m_ObjectHideFlags: 0\n  serializedVersion: 3\n  m_"
  },
  {
    "path": "ProjectSettings/EditorBuildSettings.asset",
    "chars": 138,
    "preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!1045 &1\nEditorBuildSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion:"
  },
  {
    "path": "ProjectSettings/InputManager.asset",
    "chars": 5793,
    "preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!13 &1\nInputManager:\n  m_ObjectHideFlags: 0\n  serializedVersion: 2\n  m_Ax"
  },
  {
    "path": "ProjectSettings/NavMeshAreas.asset",
    "chars": 894,
    "preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!126 &1\nNavMeshProjectSettings:\n  m_ObjectHideFlags: 0\n  serializedVersio"
  },
  {
    "path": "ProjectSettings/NetworkManager.asset",
    "chars": 151,
    "preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!149 &1\nNetworkManager:\n  m_ObjectHideFlags: 0\n  m_DebugLevel: 0\n  m_Send"
  },
  {
    "path": "ProjectSettings/Physics2DSettings.asset",
    "chars": 1330,
    "preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!19 &1\nPhysics2DSettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 2\n "
  },
  {
    "path": "ProjectSettings/QualitySettings.asset",
    "chars": 4574,
    "preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!47 &1\nQualitySettings:\n  m_ObjectHideFlags: 0\n  serializedVersion: 5\n  m"
  },
  {
    "path": "ProjectSettings/TagManager.asset",
    "chars": 378,
    "preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!78 &1\nTagManager:\n  serializedVersion: 2\n  tags: []\n  layers:\n  - Defaul"
  },
  {
    "path": "ProjectSettings/TimeManager.asset",
    "chars": 202,
    "preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!5 &1\nTimeManager:\n  m_ObjectHideFlags: 0\n  Fixed Timestep: 0.02\n  Maximu"
  },
  {
    "path": "ProjectSettings/UnityConnectSettings.asset",
    "chars": 673,
    "preview": "%YAML 1.1\n%TAG !u! tag:unity3d.com,2011:\n--- !u!310 &1\nUnityConnectSettings:\n  m_ObjectHideFlags: 0\n  m_Enabled: 0\n  m_T"
  },
  {
    "path": "README.md",
    "chars": 8473,
    "preview": "# AsImpL (OBJ)\n### Asynchronous Importer and run-time Loader for Unity\n**Requires Unity 5.5.4 or higher.**\n\nLoad 3D mode"
  },
  {
    "path": "models/OBJ_test/README.txt",
    "chars": 163,
    "preview": "The 3D models in this folder are made by Giovanni Paolo Vigan (GPV) using Anim8or.\nTextures were created by GPV using GI"
  },
  {
    "path": "models/OBJ_test/objtest.mtl",
    "chars": 980,
    "preview": "# Wavefront material file\n# Sample materials\n\nnewmtl DiffBump\nKa 0.117647 0.117647 0.117647\nKd 0.54902 0.54902 0.54902\nK"
  },
  {
    "path": "models/OBJ_test/objtest_yup.obj",
    "chars": 438047,
    "preview": "# Created with Anim8or 0.98\n# Object \"objtest\":\n\nmtllib objtest.mtl\n\n# Shape \"mesh01\":\ng mesh01\n# No. points 1938:\nv -1."
  },
  {
    "path": "models/OBJ_test/objtest_zup.obj",
    "chars": 438101,
    "preview": "# Created with Anim8or 0.98\n# Object \"mtlTest\":\n\nmtllib objtest.mtl\n\n# Shape \"DiffBump\":\ng DiffBump\n# No. points 1938:\nv"
  },
  {
    "path": "models/OBJ_test/testBumpRefl.obj",
    "chars": 83972,
    "preview": "# Created with Anim8or 0.98 [edited by GPV]\n# Object \"BumpRefl\":\n\nmtllib objtest.mtl\n\n# Shape \"BumpRefl\":\ng BumpRefl\n# N"
  },
  {
    "path": "models/OBJ_test/testDiffBump.obj",
    "chars": 83972,
    "preview": "# Created with Anim8or 0.98 [edited by GPV]\n# Object \"DiffBump\":\n\nmtllib objtest.mtl\n\n# Shape \"DiffBump\":\ng DiffBump\n# N"
  },
  {
    "path": "models/OBJ_test/testDiffOpacity.obj",
    "chars": 83987,
    "preview": "# Created with Anim8or 0.98 [edited by GPV]\n# Object \"DiffOpacity\":\n\nmtllib objtest.mtl\n\n# Shape \"DiffOpacity\":\ng DiffOp"
  },
  {
    "path": "models/OBJ_test/testRefl.obj",
    "chars": 83952,
    "preview": "# Created with Anim8or 0.98 [edited by GPV]\n# Object \"Refl\":\n\nmtllib objtest.mtl\n\n# Shape \"Refl\":\ng Refl\n# No. points 38"
  },
  {
    "path": "models/OBJ_test/testTransp.obj",
    "chars": 83962,
    "preview": "# Created with Anim8or 0.98 [edited by GPV]\n# Object \"Transp\":\n\nmtllib objtest.mtl\n\n# Shape \"Transp\":\ng Transp\n# No. poi"
  },
  {
    "path": "models/object_list_test.xml",
    "chars": 4872,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ArrayOfModelImportInfo xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xm"
  },
  {
    "path": "package.json",
    "chars": 494,
    "preview": "{\n\t\"name\": \"com.gpvigano.asimpl\",\n\t\"displayName\": \"AsImpL\",\n\t\"version\": \"1.0.0\",\n\t\"description\": \"Asynchronous Importer "
  }
]

// ... and 15 more files (download for full content)

About this extraction

This page contains the full source code of the gpvigano/AsImpL GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 142 files (1.5 MB), approximately 855.3k tokens, and a symbol index with 205 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!