Program Listing for File SceneLoader.cpp

Return to documentation for file (SPlisHSPlasH/Utilities/SceneLoader.cpp)

#include "SceneLoader.h"
#include <iostream>
#include "extern/json/json.hpp"
#include <fstream>
#include "Utilities/FileSystem.h"
#include "Utilities/Logger.h"

using namespace Utilities;
using namespace GenParam;
using namespace std;


void SceneLoader::readScene(const char *fileName, Scene &scene)
{
    LOG_INFO << "Load scene file: " << fileName;

    std::ifstream input_file(fileName);
    if (!input_file.is_open())
    {
        LOG_ERR << "Cannot open file!";
        return;
    }
    try
    {
        m_jsonData = nlohmann::json::parse(input_file);
    }
    catch (const std::exception& e)
    {
        LOG_ERR << e.what();
        exit(1);
    }

    std::string base_path = FileSystem::getFilePath(fileName);

    // read configuration
    if (m_jsonData.find("Configuration") != m_jsonData.end())
    {
        nlohmann::json config = m_jsonData["Configuration"];

        scene.particleRadius = 0.025;
        readValue(config["particleRadius"], scene.particleRadius);

        scene.sim2D = false;
        readValue(config["sim2D"], scene.sim2D);
    }

    // read boundary models
    if (m_jsonData.find("RigidBodies") != m_jsonData.end())
    {
        nlohmann::json boundaryModels = m_jsonData["RigidBodies"];
        for (auto& boundaryModel : boundaryModels)
        {
            BoundaryParameterObject* data = new BoundaryParameterObject();
            data->initParameters();
            readParameterObject(boundaryModel, data);
            data->axis.normalize();
            if ((data->meshFile != "") || (data->samplesFile != ""))
                scene.boundaryModels.push_back(data);
            else
                delete data;
        }
    }


    // read fluid models
    if (m_jsonData.find("FluidModels") != m_jsonData.end())
    {
        nlohmann::json fluidModels = m_jsonData["FluidModels"];
        for (auto& fluidModel : fluidModels)
        {
            FluidModelParameterObject* data = new FluidModelParameterObject();
            data->initParameters();
            readParameterObject(fluidModel, data);
            data->axis.normalize();
            scene.fluidModels.push_back(data);
        }
    }

    // read fluid blocks
    if (m_jsonData.find("FluidBlocks") != m_jsonData.end())
    {
        nlohmann::json fluidBlocks = m_jsonData["FluidBlocks"];
        for (auto& fluidBlock : fluidBlocks)
        {
            FluidBlockParameterObject *block = new FluidBlockParameterObject();
            block->initParameters();
            readParameterObject(fluidBlock, block);
            scene.fluidBlocks.push_back(block);
        }
    }

    // read emitters
    if (m_jsonData.find("Emitters") != m_jsonData.end())
    {
        nlohmann::json emitters = m_jsonData["Emitters"];
        for (auto& emitter : emitters)
        {
            EmitterParameterObject *data = new EmitterParameterObject();
            data->initParameters();
            readParameterObject(emitter, data);

            // in 2D simulations always rotate around z-axis
            if (scene.sim2D)
                data->axis = { 0.0, 0.0, 1.0 };
            data->axis.normalize();
            scene.emitters.push_back(data);
        }
    }

    // read animation fields
    if (m_jsonData.find("AnimationFields") != m_jsonData.end())
    {
        nlohmann::json fields = m_jsonData["AnimationFields"];
        for (auto& field : fields)
        {
            AnimationFieldParameterObject* data = new AnimationFieldParameterObject();
            data->initParameters();
            readParameterObject(field, data);
            data->axis.normalize();
            scene.animatedFields.push_back(data);
        }
    }

    // read materials
    if (m_jsonData.find("Materials") != m_jsonData.end())
    {
        nlohmann::json materials = m_jsonData["Materials"];
        for (auto& material : materials)
        {
            MaterialParameterObject* data = new MaterialParameterObject();
            data->initParameters();
            readParameterObject(material, data);
            scene.materials.push_back(data);
        }
    }
}


template <>
bool SceneLoader::readValue(const nlohmann::json &j, bool &v)
{
    if (j.is_null())
        return false;

    if (j.is_number_integer())
    {
        int val = j.get<int>();
        v = val != 0;
    }
    else
        v = j.get<bool>();
    return true;
}

void SceneLoader::readMaterialParameterObject(const std::string &key, ParameterObject *paramObj)
{
    if (paramObj == nullptr)
        return;

    if (m_jsonData.find("Materials") != m_jsonData.end())
    {
        nlohmann::json materials = m_jsonData["Materials"];
        for (auto& material : materials)
        {
            string id = "";
            readValue(material["id"], id);

            if (key == id)
            {
                readParameterObject(material, paramObj);
            }
        }
    }
}

void SceneLoader::readMaterialParameterObject(const std::string& key, SPH::NonPressureForceBase* paramObj)
{
    if (paramObj == nullptr)
        return;

    if (m_jsonData.find("Materials") != m_jsonData.end())
    {
        nlohmann::json &materials = m_jsonData["Materials"];
        for (auto& material : materials)
        {
            string id = "";
            readValue(material["id"], id);

            if (key == id)
            {
                if (material.find(paramObj->getMethodName()) != material.end())
                {
                    nlohmann::json &material_section = material[paramObj->getMethodName()];
                    if (!material_section.is_null())
                        readParameterObject(material_section, paramObj);
                }
            }
        }
    }
}

void SceneLoader::readParameterObject(const std::string& key, ParameterObject* paramObj)
{
    if (paramObj == nullptr)
        return;

    // read configuration
    if (m_jsonData.find(key) != m_jsonData.end())
    {
        nlohmann::json config = m_jsonData[key];
        readParameterObject(config, paramObj);
    }
}

void SceneLoader::readTimeStepParameterObject(const std::string& key, SPH::TimeStep* paramObj)
{
    if (paramObj == nullptr)
        return;

    // read configuration
    if (m_jsonData.find(key) != m_jsonData.end())
    {
        nlohmann::json config = m_jsonData[key];
        if (config.find(paramObj->getMethodName()) != config.end())
        {
            nlohmann::json& method_section = config[paramObj->getMethodName()];
            if (!method_section.is_null())
                readParameterObject(method_section, paramObj);
        }
    }
}

void SceneLoader::readParameterObject(nlohmann::json& config, ParameterObject* paramObj)
{
    if (paramObj == nullptr)
        return;

    const unsigned int numParams = paramObj->numParameters();
    for (unsigned int i = 0; i < numParams; i++)
    {
        ParameterBase* paramBase = paramObj->getParameter(i);

        if (paramBase->getType() == RealParameterType)
        {
            Real val;
            if (readValue(config[paramBase->getName()], val))
                static_cast<NumericParameter<Real>*>(paramBase)->setValue(val);
        }
        else if (paramBase->getType() == ParameterBase::UINT32)
        {
            unsigned int val;
            if (readValue(config[paramBase->getName()], val))
                static_cast<NumericParameter<unsigned int>*>(paramBase)->setValue(val);
        }
        else if (paramBase->getType() == ParameterBase::UINT16)
        {
            unsigned short val;
            if (readValue(config[paramBase->getName()], val))
                static_cast<NumericParameter<unsigned short>*>(paramBase)->setValue(val);
        }
        else if (paramBase->getType() == ParameterBase::UINT8)
        {
            unsigned char val;
            if (readValue(config[paramBase->getName()], val))
                static_cast<NumericParameter<unsigned char>*>(paramBase)->setValue(val);
        }
        else if (paramBase->getType() == ParameterBase::INT32)
        {
            int val;
            if (readValue(config[paramBase->getName()], val))
                static_cast<NumericParameter<int>*>(paramBase)->setValue(val);
        }
        else if (paramBase->getType() == ParameterBase::INT16)
        {
            short val;
            if (readValue(config[paramBase->getName()], val))
                static_cast<NumericParameter<short>*>(paramBase)->setValue(val);
        }
        else if (paramBase->getType() == ParameterBase::INT8)
        {
            char val;
            if (readValue(config[paramBase->getName()], val))
                static_cast<NumericParameter<char>*>(paramBase)->setValue(val);
        }
        else if (paramBase->getType() == ParameterBase::ENUM)
        {
            int val;
            if (readValue(config[paramBase->getName()], val))
                static_cast<EnumParameter*>(paramBase)->setValue(val);
        }
        else if (paramBase->getType() == ParameterBase::BOOL)
        {
            bool val;
            if (readValue(config[paramBase->getName()], val))
                static_cast<BoolParameter*>(paramBase)->setValue(val);
        }
        else if (paramBase->getType() == RealVectorParameterType)
        {
            if (static_cast<VectorParameter<Real>*>(paramBase)->getDim() == 3)
            {
                Vector3r val;
                if (readVector(config[paramBase->getName()], val))
                    static_cast<VectorParameter<Real>*>(paramBase)->setValue(val.data());
            }
            else if (static_cast<VectorParameter<Real>*>(paramBase)->getDim() == 4)
            {
                Vector4r val;
                if (readVector(config[paramBase->getName()], val))
                    static_cast<VectorParameter<Real>*>(paramBase)->setValue(val.data());
            }
        }
        else if (paramBase->getType() == ParameterBase::VEC_UINT32)
        {
            if (static_cast<VectorParameter<unsigned int>*>(paramBase)->getDim() == 3)
            {
                Eigen::Matrix<unsigned int, 3, 1, Eigen::DontAlign> val;
                if (readVector(config[paramBase->getName()], val))
                    static_cast<VectorParameter<unsigned int>*>(paramBase)->setValue(val.data());
            }
        }
        else if (paramBase->getType() == ParameterBase::STRING)
        {
            std::string val;
            if (readValue(config[paramBase->getName()], val))
                static_cast<StringParameter*>(paramBase)->setValue(val);
        }
    }
}