Search code examples
c++assimp

Constructor cannot Initialize one parameter when it exits the function


I am against one problem with my C++ code. I am using the Assimp library, and I have one class that has one attribute of type const aiScene*. In the constructor of the class, I assign this value and all works fine, but when I exit the constructor code, the parameter const aiScene* does not have any data assigned

I paste you here the code.

Model.h

class Model
{
public:
    Model(std::string objectLoc, std::string vertexLoc, std::string fragmentLoc,
    glm::vec3 position, glm::vec3 scale, glm::vec3 rotation,
    Camera* camera);

    void render();

    ~Model();

private:
    std::string objectLoc, vertexLoc, fragmentLoc;
    Shader* shader;
    glm::mat4 model;
    glm::vec3 position, scale, rotation;
    Camera* camera;

    std::vector<Mesh*> meshes;
    std::vector<Texture*> textures;

    std::vector<unsigned int> meshToTex;
    std::unordered_map<std::string, GLuint> boneMapping;
    std::vector<glm::mat4> bonesTransformations;

    const aiScene* scene;

    glm::mat4 globalInverseTransform;

    GLuint boneCount;
};

Model.cpp

Model::Model(std::string objectLoc, std::string vertexLoc, std::string fragmentLoc, glm::vec3 
position, glm::vec3 scale, glm::vec3 rotation, Camera* camera)
: objectLoc(objectLoc), vertexLoc(vertexLoc), fragmentLoc(fragmentLoc),
position(position), scale(scale), rotation(rotation),
camera(camera),
boneCount(0)
{
    shader = new Shader(vertexLoc, fragmentLoc,
    DirectionalLight(glm::vec3(1.0f, 1.0f, 1.0f), 0.4f, 0.1f, glm::vec3(0.0f, 0.0f, -1.0f)),
    SpecularLight(1.0f, 250.0f),
    SpotLight(glm::vec3(1.0f, 1.0f, 1.0f), 0.0f, 1.0f, glm::vec3(0.0f, 0.0f, 0.0f), 1.0f, 0.0f, 0.0f, 
    glm::vec3(0.0f, 0.0f, -1.0f), glm::radians(10.0f)));

    shader->addPointLight(PointLight(glm::vec3(1.0f, 0.0f, 0.0f), 0.2f, 0.2f, glm::vec3(0.0f, 0.0f, 
-15.0f), 0.3f, 0.2f, 0.1f));
    shader->addPointLight(PointLight(glm::vec3(0.0f, 1.0f, 0.0f), 0.2f, 0.2f, glm::vec3(10.0f, 0.0f, 
-15.0f), 0.3f, 0.2f, 0.1f));
    shader->addPointLight(PointLight(glm::vec3(0.0f, 0.0f, 1.0f), 0.2f, 1.2f, glm::vec3(-10.0f, 0.0f, 
-15.0f), 0.8f, 0.2f, 0.1f));

    model = glm::translate(glm::mat4(1.0f), position)
        * glm::scale(glm::mat4(1.0f), scale)
        * glm::rotate(glm::mat4(1.0f), glm::radians(rotation.x), glm::vec3(1, 0, 0))
        * glm::rotate(glm::mat4(1.0f), glm::radians(rotation.y), glm::vec3(0, 1, 0))
        * glm::rotate(glm::mat4(1.0f), glm::radians(rotation.z), glm::vec3(0, 0, 1));

    Assimp::Importer importer;

    scene = importer.ReadFile(objectLoc,
        aiProcess_Triangulate |
        aiProcess_FlipUVs |
        aiProcess_GenSmoothNormals |
        aiProcess_JoinIdenticalVertices);

    if (!scene)
    {
        printf("Cannot load model %s: %s\n", objectLoc.c_str(), importer.GetErrorString());
        return;
    }

    aiNode* rootNode = scene->mRootNode;
    globalInverseTransform = aiMatrix4x4ToGlm(rootNode->mTransformation.Inverse());
    loadNode(rootNode);
    loadTextures();
}

I have tried everything, from copy one by one the attributes to the object scene, to make a clone method in all classes involved, but nothing. Even, I have thought that the problem could be the const identifier in the scene attribute, but if I make the object not constant, it works wrongly the same.

I am not modifying that attribute in any of the methods of the Model class.

I paste you here some photos of the problem.

Good result in the constructor

Bad result out of the constructor

If you could help me it would be great.


Solution

  • The documentation says

    The returned data is intended to be read-only, the importer object keeps ownership of the data and will destroy it upon destruction.

    [Assimp::Importer::ReadFile]

    When the constructor is left Assimp::Importer importer; and the object scene is pointing to are destroyed.

    You have to make a copy of it before you leave the constructor or

    Use GetOrphanedScene() to take ownership of it.

    [Assimp::Importer::ReadFile]

    aiScene* Assimp::Importer::GetOrphanedScene ( )
    Returns the scene loaded by the last successful call to ReadFile() and releases the scene from the ownership of the Importer instance.

    The application is now responsible for deleting the scene. Any further calls to GetScene() or GetOrphanedScene() will return NULL - until a new scene has been loaded via ReadFile().

    Returns: Current scene or NULL if there is currently no scene loaded

    Note: Use this method with maximal caution, and only if you have to. By design, aiScene's are exclusively maintained, allocated and deallocated by Assimp and no one else. The reasoning behind this is the golden rule that deallocations should always be done by the module that did the original allocation because heaps are not necessarily shared. GetOrphanedScene() enforces you to delete the returned scene by yourself, but this will only be fine if and only if you're using the same heap as assimp. On Windows, it's typically fine provided everything is linked against the multithreaded-dll version of the runtime library. It will work as well for static linkage with Assimp.

    [Assimp::Importer::GetOrphanedScene]