ことれいのもり

Assimpを使ったときの謎のエラーはAssimp::ImporterとaiSceneの寿命のせいかもしれない

はじめに

Assimpを使用していて変なところでエラーが出たことはないでしょうか。

その場合、Assimp::ImporterもしくはaiSceneが破棄されていることが原因かもしれません。

前提

言語

参考リンク

エラーが起きる状況

Assimpを使っていて、以下のようなよく分からないところで例外がスローされることがあります。

今回だとaiMeshで読み取りアクセス違反が起こっています。

Assimpのエラー画像

プログラム自体にミスが見当たらなくて原因が分からないことがあります。

この場合、エラーが出ている場所で問題が起こっているのではなく、Assimpを使って読み込みをしている部分に問題がある可能性があります。

解決方法

Assimpでデータを読み込むとき、Assimp::importerとaiSceneを使いますよね。

このとき、importerが破棄されるとaiSceneも一緒に破棄されます!

そのため、メンバ変数にして持っておくなどして両者の寿命をのばす必要があります。

このようにメンバ変数として保持しておけば大丈夫です。

FBXModelComponent.h

class FBXModelComponent : public Component
{
public:
    /// @brief コンストラクタ
    /// @param fbxFilePath FBXモデルのパス 
    FBXModelComponent(const FilePath& fbxFilePath, const Optional<FilePath>& texFilePath = none);
    ~FBXModelComponent();

private:
    Assimp::Importer importer;

    /// @brief FBXのシーンデータ
    const aiScene* scene;
}

FBXModelComponnet.cpp

FBXModelComponent::FBXModelComponent(const FilePath& fbxFilePath, const Optional<FilePath>& texFilePath)
{
    // ※!!!!注意!!!!!
    // importerを破棄するとsceneも一緒に破棄されます
    // importerの破棄によって様々なところでクラッシュするので取り扱いには注意すること
    // 
    // FBX読み込み
    scene = importer.ReadFile(fbxFilePath.narrow(),
        aiProcess_Triangulate
        | aiProcess_JoinIdenticalVertices
        | aiProcess_LimitBoneWeights
        | aiProcess_ImproveCacheLocality
        | aiProcess_FlipUVs
        | aiProcess_ConvertToLeftHanded
    );

    if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)
    {
        Console << U"Assimp読み込みエラー:" << Unicode::FromUTF8(importer.GetErrorString());
        return;
    }
}

関係ないところでエラーが起きているのではなく、aiSceneを介して読み込もうとしたとき、読み込み先が破棄されていて参照できないから例外がスローされていました。

言われれば単純だけど、見落としがちな部分だと思います。

困っている人はAssimp::ImporterとaiSceneの寿命を確認してみてください。

おわりに

Assimpは日本語の情報が少なくて同じようなことで困っている人が多いと思います。

今回は特に遠く離れたところでエラーが出ることがあるので、特定するのに苦労しました。

参考になれば幸いです。