irajsb / UE4_Assimp

Assimp mesh importer for Unreal Engine
MIT License
136 stars 29 forks source link

Calling Exporter from Unreal crashes Unreal Engine #33

Closed Zi1mann closed 1 year ago

Zi1mann commented 1 year ago

Describe the bug Calling Exporter object to export AIScene to file crashes Unreal Engine

To Reproduce Exposing the function below to Blueprints and calling the function at runtime results in an access violation.

void UAIScene::EmptySceneTestExport()
 {
 aiScene testscene;
     FString dir = FPaths::ProjectDir();
     dir += FString(TEXT("Export/Scenes/test.fbx"));
     Exporter exporter;
     if (exporter.Export(&testscene, "fbx", TCHAR_TO_ANSI(*dir)) != AI_SUCCESS)
     {
         UE_LOG(LogAssimp, Fatal, TEXT("Exporting scene to fbx failed."));
     }
 }

Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x0000000000000000

assimp
assimp
assimp
assimp
UnrealEditor_UE_Assimp!UAIScene::EmptySceneTestExport() [C:\Users\...\Documents\UnrealProjects\MyProject\Plugins\UE4_Assimp\Source\UE_Assimp\Private\AIScene.cpp:448]
UnrealEditor_CoreUObject!UObject::execCallMathFunction() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1054]
UnrealEditor_CoreUObject!ProcessLocalScriptFunction() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1188]
UnrealEditor_CoreUObject!ProcessScriptFunction<void (__cdecl*)(UObject *,FFrame &,void *)>() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1018]
UnrealEditor_CoreUObject!ProcessLocalFunction() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1258]
UnrealEditor_CoreUObject!ProcessLocalScriptFunction() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1188]
UnrealEditor_CoreUObject!ProcessScriptFunction<void (__cdecl*)(UObject *,FFrame &,void *)>() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1018]
UnrealEditor_CoreUObject!ProcessLocalFunction() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1258]
UnrealEditor_CoreUObject!ProcessLocalScriptFunction() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1188]
UnrealEditor_CoreUObject!ProcessScriptFunction<void (__cdecl*)(UObject *,FFrame &,void *)>() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1018]
UnrealEditor_CoreUObject!ProcessLocalFunction() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1258]
UnrealEditor_CoreUObject!ProcessLocalScriptFunction() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1188]
UnrealEditor_CoreUObject!UObject::ProcessInternal() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1285]
UnrealEditor_CoreUObject!UFunction::Invoke() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\Class.cpp:6455]
UnrealEditor_CoreUObject!UObject::ProcessEvent() [C:\Users\...\Documents\UE\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:2116]
UnrealEditor_Engine!AActor::ProcessEvent() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Engine\Private\Actor.cpp:1055]
UnrealEditor_Engine!FInputActionUnifiedDelegate::Execute() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Engine\Classes\Components\InputComponent.h:302]
UnrealEditor_Engine!UPlayerInput::ProcessInputStack() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Engine\Private\UserInterface\PlayerInput.cpp:1433]
UnrealEditor_EnhancedInput!UEnhancedPlayerInput::ProcessInputStack() [C:\Users\...\Documents\UE\Engine\Plugins\EnhancedInput\Source\EnhancedInput\Private\EnhancedPlayerInput.cpp:257]
UnrealEditor_Engine!APlayerController::ProcessPlayerInput() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Engine\Private\PlayerController.cpp:2707]
UnrealEditor_Engine!APlayerController::TickPlayerInput() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Engine\Private\PlayerController.cpp:4955]
UnrealEditor_Engine!APlayerController::PlayerTick() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Engine\Private\PlayerController.cpp:2311]
UnrealEditor_Engine!APlayerController::TickActor() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Engine\Private\PlayerController.cpp:5107]
UnrealEditor_Engine!FActorTickFunction::ExecuteTick() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Engine\Private\Actor.cpp:222]
UnrealEditor_Engine!FTickFunctionTask::DoTask() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Engine\Private\TickTaskManager.cpp:284]
UnrealEditor_Engine!TGraphTask<FTickFunctionTask>::ExecuteTask() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Core\Public\Async\TaskGraphInterfaces.h:1348]
UnrealEditor_Core!FNamedTaskThread::ProcessTasksNamedThread() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Core\Private\Async\TaskGraph.cpp:760]
UnrealEditor_Core!FNamedTaskThread::ProcessTasksUntilQuit() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Core\Private\Async\TaskGraph.cpp:649]
UnrealEditor_Core!FTaskGraphCompatibilityImplementation::WaitUntilTasksComplete() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Core\Private\Async\TaskGraph.cpp:2203]
UnrealEditor_Engine!FTickTaskSequencer::ReleaseTickGroup() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Engine\Private\TickTaskManager.cpp:565]
UnrealEditor_Engine!FTickTaskManager::RunTickGroup() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Engine\Private\TickTaskManager.cpp:1592]
UnrealEditor_Engine!UWorld::RunTickGroup() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Engine\Private\LevelTick.cpp:794]
UnrealEditor_Engine!UWorld::Tick() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Engine\Private\LevelTick.cpp:1537]
UnrealEditor_UnrealEd!UEditorEngine::Tick() [C:\Users\...\Documents\UE\Engine\Source\Editor\UnrealEd\Private\EditorEngine.cpp:1890]
UnrealEditor_UnrealEd!UUnrealEdEngine::Tick() [C:\Users\...\Documents\UE\Engine\Source\Editor\UnrealEd\Private\UnrealEdEngine.cpp:517]
UnrealEditor!FEngineLoop::Tick() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Launch\Private\LaunchEngineLoop.cpp:5367]
UnrealEditor!GuardedMain() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Launch\Private\Launch.cpp:202]
UnrealEditor!GuardedMainWrapper() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:107]
UnrealEditor!LaunchWindowsStartup() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:244]
UnrealEditor!WinMain() [C:\Users\...\Documents\UE\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:282]
UnrealEditor!__scrt_common_main_seh() [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288]
kernel32
ntdll```
irajsb commented 1 year ago
 void UAIScene::EmptySceneTestExport()
{
    // Creating a test scene
    std::unique_ptr<aiScene> scene(new aiScene());

    // TODO: Fill the scene with data (meshes, materials, etc.)

    aiMesh *mesh = new aiMesh();
    mesh->mNumVertices = 3;
    mesh->mVertices = new aiVector3D [] {{0,0,0}, {0,1,0}, {1,0,0}};
    mesh->mNumFaces = 1;
    mesh->mFaces = new aiFace[1];
    mesh->mFaces[0].mNumIndices = 3;
    mesh->mFaces[0].mIndices = new unsigned[] { 0, 1, 2 };
    mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; // workaround, issue #3778

    scene->mNumMeshes = 1;
    scene->mMeshes = new aiMesh * [] { mesh };
    scene->mNumMaterials = 1;
    scene->mMaterials = new aiMaterial * [] { new aiMaterial() };
    scene->mRootNode = new aiNode();
    scene->mRootNode->mNumMeshes = 1;
    scene->mRootNode->mMeshes = new unsigned [] { 0 };
    scene->mMetaData = new aiMetadata(); // workaround, issue #3781

    // Creating an exporter

    // Constructing the export path
    FString ExportPath = FPaths::ProjectDir();
    ExportPath=FPaths::Combine(ExportPath,"Export");
    ExportPath=FPaths::ConvertRelativePathToFull(ExportPath);
    if (!FPlatformFileManager::Get().GetPlatformFile().DirectoryExists(*ExportPath))
    {
        FPlatformFileManager::Get().GetPlatformFile().CreateDirectory(*ExportPath);
    }
    ExportPath =FPaths::Combine(ExportPath,"Test.obj");
    Assimp::Exporter exporter;

    // Exporting the scene
    if (exporter.Export(scene.get(), "obj", TCHAR_TO_ANSI(*ExportPath)) != AI_SUCCESS)
    {
        UE_LOG(LogAssimp, Fatal, TEXT("Exporting scene to fbx failed: %s"), ANSI_TO_TCHAR(exporter.GetErrorString()));
    }
}

The bug is actually within the assimp library and only happens for fbx format at CreationTimeStamp.Dump(outstream, binary, indent);
I tried the code above to export a triangle for obj format and the output is image

irajsb commented 1 year ago

Update : I changed assimp version on my pc ( in folder Plugins\UE4_Assimp\Source\ThirdParty\UE_AssimpLibrary\assimp) to latest version (using git ) and rebuilt . now fbx export also works !

Zi1mann commented 1 year ago

This looks promising, I will look into it next week. Thanks for your efforts so far.

Zi1mann commented 1 year ago

I pulled the latest master branch release and rebuild, exporting works, the obj file is written into the created directory. However, the game client still crashes - now without any crash message or entry in the log file at Saved/Logs/.

Hence I tried walking through your example code trying to find the line introducing this behavior. It already appears when populating aiScene's mMeshes container even before the exporter is called. scene->mMeshes = new aiMesh * [] { mesh }; . Commenting out that line reveals the same also happens on scene->mMaterials = new aiMaterial * [] { new aiMaterial() };, scene->mRootNode = new aiNode();

Zi1mann commented 1 year ago

It seems to be related to the way you initialize your scene, initializing it as aiScene* scene = new aiScene(); and calling the exporter accordingly exporter.Export(scene, "obj", TCHAR_TO_ANSI(*ExportPath)) seems to fix the problem. Exporting works, game does not crash anymore. I will close this issue.