A native crash can occur after export which can't be handled in .NET

Issue #78 new
Shadowth117 created an issue

Issue occurs in Nuget preview 5.0.0 Beta 1 as well as 4.1.0

With certain models, they will export correctly, aside from the skeletal node issue previously mentioned, but immediately after will crash my application. All attempts at .NET try catch blocks seem to fail for this and I would rather not resort to telling users that this feature will cause a crash on these files or to have to launch a separate application just to export a file.

Repro steps:  

Use the below commit of my tool. Extract and open the provided PSO2 .aqp file with the provided .aqn in the same directory. .Fbx and .Dae seem to crash guaranteed. Many other example files can be provided as necessary.

https://github.com/Shadowth117/PSO2-Aqua-Library/tree/3e207f42ccd4088f28a5eedcf35ec2809d85a6fd

Comments (8)

  1. Shadowth117 reporter

    Seems that files affected by this will cause this error. I assume this should be reported to the native issue tracker then?

  2. Dusan Fiolek

    Hitting similar issue currently.

    Have a code, to import data (.dae), represent it by Unity vertices/normals/indices/materials, create some render objects to visualize, but then trying to populate assimp objects from Unity data to create valid assimp scene so I can export it. It crashes Unity with :

    Obtained 32 stack frames
    0x00007ff96e8fad57 (assimp) Assimp::SceneCombiner::CopyScene
    0x00007ff96e90d904 (assimp) Assimp::Exporter::Export
    0x00007ff96e90f79a (assimp) aiExportSceneEx
    0x0000018baa4bdd40 (Mono JIT Code) (wrapper managed-to-native) object:wrapper_native_00007FF96E90F710 (intptr,string,string,intptr,uint)
    0x0000018baa4dc4b8 (Mono JIT Code) (wrapper delegate-invoke) <Module>:invoke_ReturnCode_intptr_string_string_intptr_uint (intptr,string,string,intptr,uint)
    0x0000018baa4dc399 (Mono JIT Code) Assimp.Unmanaged.AssimpLibrary:ExportScene (intptr,string,string,intptr,Assimp.PostProcessSteps)
    0x0000018baa4d845b (Mono JIT Code) Assimp.AssimpContext:ExportFile (Assimp.Scene,string,string,Assimp.PostProcessSteps)
    0x0000018baa4d8333 (Mono JIT Code) Assimp.AssimpContext:ExportFile (Assimp.Scene,string,string)
    0x0000018baa4b3803 (Mono JIT Code) [Main.cs:51] Main:Start () 
    0x0000018b8a12fac8 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
    0x00007ff96e12e4b4 (mono-2.0-bdwgc) [mini-runtime.c:3445] mono_jit_runtime_invoke 
    0x00007ff96e06e764 (mono-2.0-bdwgc) [object.c:3066] do_runtime_invoke 
    0x00007ff96e06e8fc (mono-2.0-bdwgc) [object.c:3113] mono_runtime_invoke 
    0x00007ff62ab558c4 (Unity) scripting_method_invoke
    0x00007ff62ab504e4 (Unity) ScriptingInvocation::Invoke
    0x00007ff62ab24a22 (Unity) MonoBehaviour::InvokeMethodOrCoroutineChecked
    0x00007ff62ab24b5b (Unity) MonoBehaviour::InvokeMethodOrCoroutineChecked
    0x00007ff62ab1f182 (Unity) MonoBehaviour::DelayedStartCall
    0x00007ff62a61cdb4 (Unity) DelayedCallManager::Update
    0x00007ff62a82ca99 (Unity) `InitPlayerLoopCallbacks'::`2'::EarlyUpdateScriptRunDelayedStartupFrameRegistrator::Forward
    0x00007ff62a8143cc (Unity) ExecutePlayerLoop
    0x00007ff62a8144a3 (Unity) ExecutePlayerLoop
    0x00007ff62a81a0e9 (Unity) PlayerLoop
    0x00007ff62b761778 (Unity) PlayerLoopController::UpdateScene
    0x00007ff62b74d354 (Unity) PlayerLoopController::EnterPlayMode
    0x00007ff62b75c7e7 (Unity) PlayerLoopController::SetIsPlaying
    0x00007ff62b75fbed (Unity) Application::TickTimer
    0x00007ff62bbab00a (Unity) MainMessageLoop
    0x00007ff62bbaf8bb (Unity) WinMain
    0x00007ff62cee28be (Unity) __scrt_common_main_seh
    0x00007ffa1cb67034 (KERNEL32) BaseThreadInitThunk
    0x00007ffa1cdc2651 (ntdll) RtlUserThreadStart
    

    For a sanity check I tried to create Unity render objects out of processed Assimp.Scene (assimp data → Unity data → assimp data → Unity data) to see if objects are there, and all seems to be OK and rendered fine, only export crashes.

    string inFile = @"c:\stuff\H.DAE";
            AssimpContext assimpContext = new AssimpContext();
            Scene impScene = assimpContext.ImportFile(inFile, PostProcessSteps.JoinIdenticalVertices | PostProcessSteps.Triangulate);
            var sceneData = SceneData.fromScene(impScene);
    
            string outFile = @"c:\code\out_unity.dae";
            var exp = sceneData.toAIScene();
            var sceneDataExp = SceneData.fromScene(exp);
            CreateUnityRenderData(sceneDataExp);
            assimpContext.ExportFile(exp, outFile, "obj");       
    

    public Scene toAIScene() 
        {
            Scene aiScene = new Scene();
            // meshes
            {
                foreach(var m in Meshes) {
                    aiScene.Meshes.Add(m.toAIMesh());
                }
            }
            // materials
            {
                foreach(var m in Materials) {
                    aiScene.Materials.Add(m.toAIMaterial());
                }
            }
    
            aiScene.RootNode = new Node();
    
            return aiScene;
        }
    

    public Assimp.Mesh toAIMesh() {
            Assimp.Mesh mesh = new Assimp.Mesh(this.name);
            // vertices
            {
                foreach( var v in this.positions) {
                    mesh.Vertices.Add(new Assimp.Vector3D(v.x, v.y, v.z));
                }            
            }
            // normals
            {
                foreach( var v in this.normals) {
                    mesh.Normals.Add(new Assimp.Vector3D(v.x, v.y, v.z));
                }  
            }
            // indices
            {
                mesh.SetIndices(this.indices.ToArray(), 3);
            }
    
            mesh.MaterialIndex = MaterialIndex;
    
            return mesh;
        }
    

    Am I missing something?

    Is there some minimal programmatically created Assimp.Scene (AIScene) with simple mesh and material as a sample somewhere that can be properly exported? Thank you.

  3. Nicholas Woodfield repo owner

    Is the MaterialIndex you assign actually in the range of [0, Materials.Length) ?

    That root node also should have the mesh indices assigned to it, but I don’t think that would cause a crash in the native CopyScene.

  4. Dusan Fiolek

    Hi Nicolas, thanks for reply!

    yes, Material indices look OK.

    Materials: 3
    ...
    mesh t_color_#32 MaterialIndex: 0
    mesh t_color_#16 MaterialIndex: 1
    mesh t_color_#20 MaterialIndex: 2
    

    when I tried to populate RootNode.MeshIndices with all indices from meshes in scene meshes,

    aiScene.RootNode = new Node();
            // meshes
            {
                foreach(var m in Meshes) {
                    UnityEngine.Debug.Log($"mesh {m.name} MaterialIndex: {m.MaterialIndex}");
    
                    var aiMesh = m.toAIMesh();
                    aiScene.Meshes.Add(aiMesh);
    
                    aiScene.RootNode.MeshIndices.AddRange(aiMesh.GetIndices());
                }
            }
    

    export crashed with different stacktrace:

    Obtained 35 stack frames
    0x00007ff9d627016b (assimp) Assimp::ObjFileParser::setBuffer
    0x00007ff9d6270e4f (assimp) Assimp::ObjFileParser::setBuffer
    0x00007ff9d626f355 (assimp) Assimp::ObjFileParser::setBuffer
    0x00007ff9d627020d (assimp) Assimp::ObjFileParser::setBuffer
    0x00007ff9d615dc2d (assimp) Assimp::Exporter::Export
    0x00007ff9d615f79a (assimp) aiExportSceneEx
    0x00000205eab63f8a (Mono JIT Code) (wrapper managed-to-native) object:wrapper_native_00007FF9D615F710 (intptr,string,string,intptr,uint)
    0x00000205ebb9283a (Mono JIT Code) (wrapper delegate-invoke) <Module>:invoke_ReturnCode_intptr_string_string_intptr_uint (intptr,string,string,intptr,uint)
    0x00000205ebb92534 (Mono JIT Code) Assimp.Unmanaged.AssimpLibrary:ExportScene (intptr,string,string,intptr,Assimp.PostProcessSteps)
    0x00000205ebb8620b (Mono JIT Code) Assimp.AssimpContext:ExportFile (Assimp.Scene,string,string,Assimp.PostProcessSteps)
    0x00000205ebb85e53 (Mono JIT Code) Assimp.AssimpContext:ExportFile (Assimp.Scene,string,string)
    0x00000205e8b3228b (Mono JIT Code) [Main.cs:34] Main:Start () 
    0x00000206937ac628 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
    0x00007ff9cfdae4b4 (mono-2.0-bdwgc) [mini-runtime.c:3445] mono_jit_runtime_invoke 
    0x00007ff9cfcee764 (mono-2.0-bdwgc) [object.c:3066] do_runtime_invoke 
    0x00007ff9cfcee8fc (mono-2.0-bdwgc) [object.c:3113] mono_runtime_invoke 
    0x00007ff68e1a58c4 (Unity) scripting_method_invoke
    0x00007ff68e1a04e4 (Unity) ScriptingInvocation::Invoke
    0x00007ff68e174a22 (Unity) MonoBehaviour::InvokeMethodOrCoroutineChecked
    0x00007ff68e174b5b (Unity) MonoBehaviour::InvokeMethodOrCoroutineChecked
    0x00007ff68e16f182 (Unity) MonoBehaviour::DelayedStartCall
    0x00007ff68dc6cdb4 (Unity) DelayedCallManager::Update
    0x00007ff68de7ca99 (Unity) `InitPlayerLoopCallbacks'::`2'::EarlyUpdateScriptRunDelayedStartupFrameRegistrator::Forward
    0x00007ff68de643cc (Unity) ExecutePlayerLoop
    0x00007ff68de644a3 (Unity) ExecutePlayerLoop
    0x00007ff68de6a0e9 (Unity) PlayerLoop
    0x00007ff68edb1778 (Unity) PlayerLoopController::UpdateScene
    0x00007ff68ed9d354 (Unity) PlayerLoopController::EnterPlayMode
    0x00007ff68edac7e7 (Unity) PlayerLoopController::SetIsPlaying
    0x00007ff68edafbed (Unity) Application::TickTimer
    0x00007ff68f1fb00a (Unity) MainMessageLoop
    0x00007ff68f1ff8bb (Unity) WinMain
    0x00007ff6905328be (Unity) __scrt_common_main_seh
    0x00007ffa1cb67034 (KERNEL32) BaseThreadInitThunk
    0x00007ffa1cdc2651 (ntdll) RtlUserThreadStart
    

    Do you know if there is some minimal code for export without actually importing, but with creating mesh/scene from scratch? Thanks.

  5. Nicholas Woodfield repo owner

    aiScene.RootNode.MeshIndices.AddRange(aiMesh.GetIndices());
    

    Erm no, I meant the indices of the mesh objects (like the material index), sorry. So range of [0, Meshes.Length). The fact you got passed the native CopyScene and into an exporter though is promising.

    There’s a minimal example in the unit tests, but it more or less looks like your code snippets.

    Also I missed your outFile is “dae” and you’re passing in an export format hint as “obj”, again I don’t think that should impact, but I’m not sure if the native assimp will change the file extension or not so it may be unexpected to you.

  6. Dusan Fiolek

    Ah yes, my bad, sorry.. mesh indices.. not mesh vertex indices.. didn’t make sense to me, but was confused by name..

    adding

    aiScene.RootNode = new Node();
    aiScene.RootNode.MeshIndices.AddRange(Enumerable.Range(0, Meshes.Count).ToList());
    

    did the trick and I was able to export the modified scene finally.

    Thank you very much !

  7. Log in to comment