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 << 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.timeStepSize = 0.001;
readValue(config["timeStepSize"], scene.timeStepSize);
scene.particleRadius = 0.025;
readValue(config["particleRadius"], scene.particleRadius);
scene.sim2D = false;
readValue(config["sim2D"], scene.sim2D);
if (scene.sim2D)
scene.camPosition = Vector3r(0.0, 0.0, 8.0);
else
scene.camPosition = Vector3r(0.0, 3.0, 8.0);
readVector(config["cameraPosition"], scene.camPosition);
scene.camLookat = Vector3r(0.0, 0.0, 0.0);
readVector(config["cameraLookat"], scene.camLookat);
}
// read boundary models
if (m_jsonData.find("RigidBodies") != m_jsonData.end())
{
nlohmann::json boundaryModels = m_jsonData["RigidBodies"];
for (auto& boundaryModel : boundaryModels)
{
std::string particleFile = "";
std::string meshFile = "";
std::string mapFile = "";
const bool bMesh = readValue<std::string>(boundaryModel["geometryFile"], meshFile);
const bool bSamples = readValue<std::string>(boundaryModel["particleFile"], particleFile);
const bool bMap = readValue<std::string>(boundaryModel["mapFile"], mapFile);
if (bMesh || bSamples)
{
BoundaryData *data = new BoundaryData();
data->meshFile = meshFile;
data->samplesFile = particleFile;
data->mapFile = mapFile;
// translation
data->translation = Vector3r::Zero();
readVector(boundaryModel["translation"], data->translation);
// rotation axis
Vector3r axis = Vector3r::Zero();
Real angle = 0.0;
data->rotation = Matrix3r::Identity();
if (readVector(boundaryModel["rotationAxis"], axis) &&
readValue<Real>(boundaryModel["rotationAngle"], angle))
data->rotation = AngleAxisr(angle, axis);
// scale
data->scale = Vector3r::Ones();
readVector(boundaryModel["scale"], data->scale);
data->dynamic = false;
readValue<bool>(boundaryModel["isDynamic"], data->dynamic);
data->isWall = false;
readValue<bool>(boundaryModel["isWall"], data->isWall);
data->color = Eigen::Vector4f(1.0f, 0.0f, 0.0f, 0.0f);
readVector(boundaryModel["color"], data->color);
data->samplingMode = 0;
readValue<unsigned int>(boundaryModel["samplingMode"], data->samplingMode);
data->isAnimated = false;
readValue<bool>(boundaryModel["isAnimated"], data->isAnimated);
// Maps
data->mapInvert = false;
readValue(boundaryModel["mapInvert"], data->mapInvert);
data->mapThickness = 0.0;
readValue(boundaryModel["mapThickness"], data->mapThickness);
data->mapResolution = Eigen::Matrix<unsigned int, 3, 1>(20, 20, 20);
readVector(boundaryModel["mapResolution"], data->mapResolution);
scene.boundaryModels.push_back(data);
}
}
}
// read fluid models
if (m_jsonData.find("FluidModels") != m_jsonData.end())
{
nlohmann::json fluidModels = m_jsonData["FluidModels"];
for (auto& fluidModel : fluidModels)
{
std::string particleFile;
if (readValue<std::string>(fluidModel["particleFile"], particleFile))
{
FluidData *data = new FluidData();
data->samplesFile = particleFile;
// id
data->id = "Fluid";
readValue(fluidModel["id"], data->id);
// translation
data->translation = Vector3r::Zero();
readVector(fluidModel["translation"], data->translation);
// rotation axis
Vector3r axis = Vector3r::Zero();
Real angle = 0.0;
data->rotation = Matrix3r::Identity();
if (readVector(fluidModel["rotationAxis"], axis) &&
readValue<Real>(fluidModel["rotationAngle"], angle))
data->rotation = AngleAxisr(angle, axis);
// scale
data->scale = Vector3r::Ones();
readVector(fluidModel["scale"], data->scale);
// velocity
data->initialVelocity = Vector3r::Zero();
readVector(fluidModel["initialVelocity"], data->initialVelocity);
// angular velocity
data->initialAngularVelocity = Vector3r::Zero();
readVector(fluidModel["initialAngularVelocity"], data->initialAngularVelocity);
data->invert = false;
readValue(fluidModel["invert"], data->invert);
data->resolutionSDF = { 20, 20, 20 };
Eigen::Matrix<unsigned int, 3, 1, Eigen::DontAlign> res(20,20,20);
readVector(fluidModel["resolutionSDF"], res);
data->resolutionSDF[0] = res[0];
data->resolutionSDF[1] = res[1];
data->resolutionSDF[2] = res[2];
data->mode = 0;
readValue(fluidModel["denseMode"], data->mode);
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)
{
// translation
Vector3r translation = Vector3r::Zero();
readVector(fluidBlock["translation"], translation);
// scale
Vector3r scale = Vector3r::Ones();
readVector(fluidBlock["scale"], scale);
Vector3r minX, maxX;
if (readVector(fluidBlock["start"], minX) &&
readVector(fluidBlock["end"], maxX))
{
FluidBlock *block = new FluidBlock();
block->box.m_minX[0] = scale[0] * minX[0] + translation[0];
block->box.m_minX[1] = scale[1] * minX[1] + translation[1];
block->box.m_minX[2] = scale[2] * minX[2] + translation[2];
block->box.m_maxX[0] = scale[0] * maxX[0] + translation[0];
block->box.m_maxX[1] = scale[1] * maxX[1] + translation[1];
block->box.m_maxX[2] = scale[2] * maxX[2] + translation[2];
// id
block->id = "Fluid";
readValue(fluidBlock["id"], block->id);
readValue(fluidBlock["denseMode"], block->mode);
// velocity
block->initialVelocity = Vector3r::Zero();
readVector(fluidBlock["initialVelocity"], block->initialVelocity);
// angular velocity
block->initialAngularVelocity = Vector3r::Zero();
readVector(fluidBlock["initialAngularVelocity"], block->initialAngularVelocity);
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)
{
EmitterData *data = new EmitterData();
// id
data->id = "Fluid";
readValue(emitter["id"], data->id);
// width
data->width = 5;
readValue(emitter["width"], data->width);
// height
data->height = 5;
readValue(emitter["height"], data->height);
// translation
data->x = Vector3r::Zero();
readVector(emitter["translation"], data->x);
// rotation
// default direction without rotation is +x
Vector3r axis(0,0,1);
Real angle = 0.0;
data->rotation = Matrix3r::Identity();
if (readVector(emitter["rotationAxis"], axis) &&
readValue(emitter["rotationAngle"], angle))
{
// in 2D simulations always rotate around z-axis
if (scene.sim2D)
axis = { 0.0, 0.0, 1.0 };
axis.normalize();
data->rotation = AngleAxisr(angle, axis).toRotationMatrix();
}
// emission velocity
data->velocity = 1;
readValue(emitter["velocity"], data->velocity);
// time when emission starts and stops
data->emitStartTime = 0;
readValue(emitter["emitStartTime"], data->emitStartTime);
data->emitEndTime = std::numeric_limits<Real>::max();
readValue(emitter["emitEndTime"], data->emitEndTime);
// type: 0 = rectangular, 1 = circle
data->type = 0;
readValue(emitter["type"], data->type);
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)
{
AnimationFieldData * data = new AnimationFieldData();
data->particleFieldName = "";
readValue(field["particleField"], data->particleFieldName);
data->expression[0] = "";
readValue(field["expression_x"], data->expression[0]);
data->expression[1] = "";
readValue(field["expression_y"], data->expression[1]);
data->expression[2] = "";
readValue(field["expression_z"], data->expression[2]);
// 0=Box, 1=Cylinder
data->shapeType = 0;
readValue(field["shapeType"], data->shapeType);
// time when emission starts and stops
data->startTime = 0;
readValue(field["startTime"], data->startTime);
data->endTime = std::numeric_limits<Real>::max();
readValue(field["endTime"], data->endTime);
data->scale= Vector3r::Ones();
readVector(field["scale"], data->scale);
// shape position
data->x = Vector3r::Zero();
readVector(field["translation"], data->x);
// rotation
// default direction without rotation is +x
Vector3r axis = Vector3r::Zero();
Real angle = 0.0;
data->rotation = Matrix3r::Identity();
if (readVector(field["rotationAxis"], axis) &&
readValue(field["rotationAngle"], angle))
{
axis.normalize();
data->rotation = AngleAxisr(angle, axis).toRotationMatrix();
}
scene.animatedFields.push_back(data);
}
}
// read animation fields
if (m_jsonData.find("Materials") != m_jsonData.end())
{
nlohmann::json materials = m_jsonData["Materials"];
for (auto& material : materials)
{
MaterialData* data = new MaterialData();
data->id = "Fluid";
readValue(material["id"], data->id);
data->minVal = 0.0;
readValue(material["renderMinValue"], data->minVal);
data->maxVal = 10.0;
readValue(material["renderMaxValue"], data->maxVal);
data->colorField = "velocity";
readValue(material["colorField"], data->colorField);
data->colorMapType = 1;
readValue(material["colorMapType"], data->colorMapType);
data->maxEmitterParticles = 10000;
readValue(material["maxEmitterParticles"], data->maxEmitterParticles);
data->emitterReuseParticles = false;
readValue(material["emitterReuseParticles"], data->emitterReuseParticles);
data->emitterBoxMin = Vector3r(-1.0, -1.0, -1.0);
readVector(material["emitterBoxMin"], data->emitterBoxMin);
data->emitterBoxMax = Vector3r(1.0, 1.0, 1.0);
readVector(material["emitterBoxMax"], data->emitterBoxMax);
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::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::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 (paramBase->getType() == ParameterBase::STRING)
{
std::string val;
if (readValue(config[paramBase->getName()], val))
static_cast<StringParameter*>(paramBase)->setValue(val);
}
}
}