bool Scene::loadScene(std::string sceneName) {
    
    //Get scene file path
    std::string file = PathReader::getPath("", sceneName.c_str(), "xml");
    
    //Load scene file.
	tinyxml2::XMLDocument doc;
    doc.LoadFile(file.c_str());
    
    //Invalid xml.
    if(doc.ErrorID() != XML_NO_ERROR) {
        
        cubeMappingSkybox = nullptr;
        light = nullptr;
        
        errorDescription = "Scene file doesn't exists.";
        return true;
    }
    
    //Variable used to flag the scene as erroneous.
    bool errorsInScene = false;
    
    //Get scene type.
    //Assume spectral as default.
    std::string sceneType = doc.RootElement()->Attribute("type");
    sceneType = sceneType == "" ? "Spectral" : sceneType;
    
    //Read camera.
    XMLElement* cameraElement = doc.RootElement()->FirstChildElement("camera");
    errorsInScene = errorsInScene || setupCamera(cameraElement);
    
    //Light.
    const XMLElement* lightElement = doc.RootElement()->FirstChildElement("light");
    const XMLElement* lightOrigin = lightElement->FirstChildElement("origin");
    
    if(lightElement) {
        
        std::string lightType = lightElement->Attribute("type");
        
        if(sceneType == "RGB") {
            
            bool rgbLightCreation = setupRGBLight(lightElement, lightOrigin, lightType);
            errorsInScene = errorsInScene || rgbLightCreation;
        } else {
            
            bool spectralLightCreation = setupSpectralLight(lightElement, lightOrigin, lightType);
            errorsInScene = errorsInScene || spectralLightCreation;
        }
    } else {
        
        errorDescription = errorDescription + "The scene doesn't contain any light.\n";
        errorsInScene = true;
    }
    
    //Eventually set a cube mapping skybox.
    setupSkyboxWithCubeMapping(doc);
    
    //Objects
    XMLElement *objectsElement = doc.RootElement()->FirstChildElement("objects");
    
    if(!objectsElement) {
        
        errorDescription = errorDescription + "The scene doesn't contain any object.\n";
        errorsInScene = true;
    }
    
    //Init geometric objects.
    for(XMLElement *objectElement = objectsElement->FirstChildElement("object");
        objectElement != NULL;
        objectElement = objectElement->NextSiblingElement("object")) {
        
        std::string type = objectElement->Attribute("type");
        
        //Object creation
        Model* object;
        bool objectCreation = setupObject(&object, objectElement);
        errorsInScene = errorsInScene || objectCreation;
        
        //Object material creation.
        const XMLElement* material = objectElement->FirstChildElement("material");
        
        if(sceneType == "RGB") {
            
            bool materialRGBCreation = setupRGBObjectMaterial(object, material);
            errorsInScene = errorsInScene || materialRGBCreation;
        } else {
            
            bool materialBRDFCreation = setupBRDFObjectMaterial(object, material);
            errorsInScene = errorsInScene || materialBRDFCreation;
        }
        
        //add object.
        objects.push_back(object);
    }
    
    //Init polygonal mesh.
    for(XMLElement *objectElement = objectsElement->FirstChildElement("mesh");
        objectElement != NULL;
        objectElement = objectElement->NextSiblingElement("mesh")) {
        
        const XMLElement* objFile = objectElement->FirstChildElement("objFile");
        
        bool backFaceCulling = false;
        
        if(attributesExist(objFile, {"backFaceCulling"})) {
            
            backFaceCulling = objFile->FindAttribute("backFaceCulling")->BoolValue();
        }
        
        std::string objName = objFile->Attribute("name");
        std::string objFilePath = PathReader::getPath("OBJs", objName.c_str(), "obj");
        
        ObjParser objParser;
        objParser.parseObj(objFilePath.c_str(), backFaceCulling);
        std::vector<Model *> pList = objParser.getPolygonalShapes();

        const XMLElement* material = objectElement->FirstChildElement("material");
        
        for(std::vector<Model *>::size_type i = 0; i != pList.size(); i++) {

            if(sceneType == "RGB") {
                
                bool materialRGBCreation = setupRGBObjectMaterial(pList[i], material);
                errorsInScene = errorsInScene || materialRGBCreation;
            } else {
                
                bool materialBRDFCreation = setupBRDFObjectMaterial(pList[i], material);
                errorsInScene = errorsInScene || materialBRDFCreation;
            }
        }
        
        //Setup AABB.
        const XMLElement* aabbElement = objectElement->FirstChildElement("aabb");
        AxisAlignedBoundingBox aabb;
        setupAABB(aabb, aabbElement);

        //Create mesh.
        Model* mesh = new PolygonalMesh(pList, aabb);
        
        //Add mesh.
        objects.push_back(mesh);
    }
    
    //SCLT specific configuration.
    errorsInScene = errorsInScene || setupSCLTParameter(doc, sceneType);
        
    return errorsInScene;
}