Lagrangian Liquid Simulation
Master Thesis project on simulation of liquids using Lagrangian approach and SPH
src/Configuration.cpp
Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 #include <iostream>
00006 #include "QString"
00007 
00008 #include "pugixml.hpp"
00009 
00010 #include "boost/tokenizer.hpp"
00011 #include <boost/algorithm/string.hpp>
00012 #include <boost/lexical_cast.hpp>
00013 #include <boost/foreach.hpp>
00014 
00015 #include "ngl/Colour.h"
00016 #include "ngl/VBOPrimitives.h"
00017 
00018 #include "Configuration.h"
00019 
00020 
00021 //static variables initialisation
00022 std::string Configuration::s_settingsDoc = "config/Settings.xml";
00023 bool Configuration::s_debug = true;
00024 ngl::Real Configuration::s_accelerationOfFreeFall = -9.28;
00025 int Configuration::s_nextParticleId = 0;
00026 int Configuration::s_nextObstacleId = -1;
00027 
00028 ngl::Colour Configuration::s_normalColour(0, 0, 1);
00029 ngl::Colour Configuration::s_boundaryColour(1, 1, 1);
00030 
00031 std::vector<ngl::Real> Configuration::getFloatVectorFromString
00032                                             (
00033                                                 const std::string _str,
00034                                                 const int _d
00035                                             )
00036 {
00037     //split string into array of strings by ","
00038     std::vector<std::string> strArray;
00039     boost::split(strArray, _str, boost::is_any_of(","));
00040 
00041     //loop through strings and convert to float array
00042     std::vector<ngl::Real> floatArray;
00043     for (int i = 0; i < _d; i++) floatArray.push_back(boost::lexical_cast<ngl::Real>(strArray[i]));
00044 
00045     //return array of float
00046     return floatArray;
00047 }
00048 
00049 void Configuration::initialiseWindow
00050                                 (
00051                                     int& o_frameRate,
00052                                     int& o_mouseMoveSensitivity,
00053                                     ngl::Real& o_timestep,
00054                                     bool& o_fpsTimerEnabled,
00055                                     bool& o_cacheEnabled,
00056                                     int& o_cacheSamplingInterval,
00057                                     bool& o_cacheAutomaticFlushEnabled,
00058                                     int& o_cacheAutomaticFlushInterval,
00059                                     bool& o_cacheExportRBDEnabled,
00060                                     bool& o_cacheExportBoundaryEnabled,
00061                                     std::string& o_path
00062                                 )
00063 {
00064     //load settings xml file
00065     pugi::xml_document doc;
00066     doc.load_file(s_settingsDoc.c_str());
00067 
00068     //load global settings here
00069     pugi::xpath_node_set node = doc.select_nodes("/Settings/Global");
00070 
00071     o_frameRate = node.first().node().attribute("fpsFrequency").as_int();
00072     o_mouseMoveSensitivity = node.first().node().attribute("mouseSensitivity").as_int();
00073     o_timestep = node.first().node().attribute("timestep").as_float();
00074     o_fpsTimerEnabled = node.first().node().attribute("fpsTimerEnabled").as_bool();
00075 
00076     //read cache parameters
00077     node = doc.select_nodes("/Settings/Cache");
00078 
00079     o_cacheEnabled = node.first().node().attribute("enabled").as_bool();
00080     o_cacheSamplingInterval = node.first().node().attribute("samplingInterval").as_int();
00081     o_cacheAutomaticFlushEnabled = node.first().node().attribute("automaticFlush").as_bool();
00082     o_cacheAutomaticFlushInterval = node.first().node().attribute("automaticFlushInterval").as_int();
00083     o_cacheExportRBDEnabled = node.first().node().attribute("exportRBD").as_bool();
00084     o_cacheExportBoundaryEnabled = node.first().node().attribute("exportBoundary").as_bool();
00085 
00086     o_path = node.first().node().attribute("path").value();
00087 
00088 }
00089 
00090 ngl::Camera Configuration::initialiseCamera(const float _aspect)
00091 {
00092     //load settings xml file
00093     pugi::xml_document doc;
00094     doc.load_file(s_settingsDoc.c_str());
00095 
00096     //get camera node
00097     pugi::xpath_node_set node = doc.select_nodes("/Settings/Camera");
00098 
00099     //get near and far plane values
00100     float near = node.first().node().attribute("near").as_float();
00101     float far = node.first().node().attribute("far").as_float();
00102 
00103     //get fov
00104     int fov = node.first().node().attribute("fov").as_int();
00105 
00106     //get from and to values and convert to float arrays
00107     std::vector<float> from = getFloatVectorFromString(node.first().node().attribute("from").value(), 3);
00108     std::vector<float> to = getFloatVectorFromString(node.first().node().attribute("to").value(), 3);
00109 
00110     //build vectors
00111     ngl::Vector eye(from[0], from[1], from[2]);
00112     ngl::Vector look(to[0], to[1], to[2]);
00113     ngl::Vector up(0, 1, 0);
00114 
00115     //create a camera with the read data
00116     ngl::Camera cam;
00117     cam.set(eye, look, up);
00118     cam.setShape(fov, _aspect, near, far, ngl::PERSPECTIVE);
00119 
00120     return cam;
00121 }
00122 
00123 ngl::Light Configuration::initialiseLight()
00124 {
00125     //load settings xml file
00126     pugi::xml_document doc;
00127     doc.load_file(s_settingsDoc.c_str());
00128 
00129     //get camera node
00130     pugi::xpath_node_set node = doc.select_nodes("/Settings/Light");
00131 
00132     //get to values and convert to float array
00133     std::vector<float> to = getFloatVectorFromString(node.first().node().attribute("to").value(), 3);
00134 
00135     //get color values and convert to float array
00136     std::vector<float> color = getFloatVectorFromString(node.first().node().attribute("color").value(), 4);
00137 
00138     //build vectors
00139     ngl::Vector direction(to[0], to[1], to[2]);
00140     ngl::Colour lightColor(color[0], color[1], color[2], color[3]);
00141 
00142     //create a light with the read data
00143     ngl::Light light(direction, lightColor, ngl::LIGHTREMOTE);
00144 
00145     return light;
00146 }
00147 
00148 std::vector<ShaderObject*>* Configuration::initialiseShader()
00149 {
00150     //load settings xml file
00151     pugi::xml_document doc;
00152     doc.load_file(s_settingsDoc.c_str());
00153 
00154     std::vector<ShaderObject*>* result = new std::vector<ShaderObject*>;
00155 
00156     //get list of normal shaders
00157     pugi::xpath_node_set node = doc.select_nodes("/Settings/Shaders/Shader");
00158     for (pugi::xpath_node_set::const_iterator it = node.begin(); it != node.end(); ++it)
00159     {
00160         //get details for a shader
00161         pugi::xpath_node node = *it;
00162 
00163         //save values in array
00164         std::string name = node.node().attribute("name").value();
00165         std::string vs = node.node().attribute("vertex").value();
00166         std::string fs = node.node().attribute("fragment").value();
00167         bool isSpecial = node.node().attribute("isSpecial").as_bool();
00168 
00169         std::vector<std::string> attribNames;
00170         std::vector<int> attribValues;
00171 
00172         if (isSpecial)
00173         {
00174             //load attributes
00175             pugi::xpath_node_set attributes = node.node().select_nodes("Attrib");
00176             for (pugi::xpath_node_set::const_iterator it1 = attributes.begin(); it1 != attributes.end(); ++it1)
00177             {
00178                 pugi::xpath_node innerNode = *it1;
00179 
00180                 std::string attribName = innerNode.node().attribute("name").value();
00181                 int value = innerNode.node().attribute("value").as_int();
00182 
00183                 attribNames.push_back(attribName);
00184                 attribValues.push_back(value);
00185             }
00186         }
00187 
00188         //create a shader and add it to our list
00189         result->push_back(new ShaderObject(name, vs, fs, attribNames, attribValues, isSpecial));
00190     }
00191 
00192     return result;
00193 }
00194 
00195 void Configuration::initialiseEnvironment
00196                                 (
00197                                     bool& o_obstacleEnabled,
00198                                     ngl::Vector& o_boundaryPosition,
00199                                     ngl::Vector& o_boundaryDimension,
00200                                     ngl::Real& o_boundaryRestitutionCoefficientForFluid,
00201                                     ngl::Real& o_boundaryRestitutionCoefficientForRBD,
00202                                     bool& o_boundaryBoundTop,
00203                                     std::vector<Particle>& o_sphereObstacleList,
00204                                     std::vector<Capsule>& o_capsuleObstacleList,
00205                                     ngl::Real& o_obstacleRestitutionCoefficient,
00206                                     bool& o_periodicWallEnabled,
00207                                     ngl::Real& o_periodicWallMaxAmplitude,
00208                                     ngl::Real& o_periodicWallSpeed,
00209                                     ngl::Real& o_periodicWallAngleIncrement,
00210                                     int& o_capsuleResolution
00211                                 )
00212 {
00213     //load settings xml file
00214     pugi::xml_document doc;
00215     doc.load_file(s_settingsDoc.c_str());
00216 
00217     //temporary variable
00218     std::vector<ngl::Real> tmp;
00219 
00220     //load global settings here
00221     pugi::xpath_node_set node = doc.select_nodes("/Settings/Environment");
00222 
00223     //read info about the boundary
00224     tmp = getFloatVectorFromString(node.first().node().select_single_node("Boundary").node().attribute("position").value(), 3);
00225     o_boundaryPosition.set(tmp[0], tmp[1], tmp[2]);
00226 
00227     tmp = getFloatVectorFromString(node.first().node().select_single_node("Boundary").node().attribute("dimension").value(), 3);
00228     o_boundaryDimension.set(tmp[0], tmp[1], tmp[2]);
00229 
00230     o_boundaryRestitutionCoefficientForFluid = node.first().node().select_single_node("Boundary").node().attribute("restitutionForFluid").as_float();
00231     o_boundaryRestitutionCoefficientForRBD = node.first().node().select_single_node("Boundary").node().attribute("restitutionForRBD").as_float();
00232 
00233     o_boundaryBoundTop = node.first().node().select_single_node("Boundary").node().attribute("boundTop").as_bool();
00234 
00235     //read info about periodic wall
00236     o_periodicWallEnabled = node.first().node().select_single_node("Boundary").node().attribute("periodicWallEnabled").as_bool();
00237 
00238     node = node.first().node().select_single_node("Boundary").node().select_nodes("PeriodicWall");
00239 
00240     o_periodicWallMaxAmplitude = node.first().node().attribute("maxAmplitude").as_float();
00241     o_periodicWallSpeed = node.first().node().attribute("speed").as_float();
00242     o_periodicWallAngleIncrement = node.first().node().attribute("angleIncrement").as_float();
00243 
00244     //read info about obstacles
00245     node = doc.select_nodes("/Settings/Environment/Obstacles");
00246     o_obstacleEnabled =  node.first().node().attribute("enabled").as_bool();
00247 
00248     o_obstacleRestitutionCoefficient = node.first().node().attribute("restitution").as_float();
00249 
00250     o_capsuleResolution = node.first().node().attribute("capsuleResolution").as_int();
00251 
00252     //get list of sphere obstacles
00253     node = node.first().node().select_nodes("Sphere");
00254     for (pugi::xpath_node_set::const_iterator it = node.begin(); it != node.end(); ++it)
00255     {
00256         //get details for an obstacle
00257         pugi::xpath_node node1 = *it;
00258 
00259         //get parameters active parameter
00260         tmp = getFloatVectorFromString(node1.node().attribute("position").value(), 3);
00261         ngl::Vector position(tmp[0], tmp[1], tmp[2]);
00262 
00263         tmp = getFloatVectorFromString(node1.node().attribute("velocity").value(), 3);
00264         ngl::Vector velocity(tmp[0], tmp[1], tmp[2]);
00265 
00266         ngl::Real radius = node1.node().attribute("radius").as_float();
00267 
00268         ngl::Real moveable = node1.node().attribute("moveable").as_bool();
00269 
00270         tmp = getFloatVectorFromString(node1.node().attribute("colour").value(), 3);
00271         ngl::Colour colour(tmp[0], tmp[1], tmp[2]);
00272 
00273         //create and add obstacle to list
00274         o_sphereObstacleList.push_back
00275                 (
00276                     Particle
00277                     (
00278                         Configuration::s_nextObstacleId--,
00279                         0,
00280                         position,
00281                         colour,
00282                         radius,
00283                         moveable,
00284                         velocity
00285                     )
00286                 );
00287     }
00288 
00289     //get list of capsule obstacles
00290     node = doc.select_nodes("/Settings/Environment/Obstacles/Capsule");
00291     for (pugi::xpath_node_set::const_iterator it = node.begin(); it != node.end(); ++it)
00292     {
00293         //get details for an obstacle
00294         pugi::xpath_node node1 = *it;
00295 
00296         //get parameters active parameter
00297         tmp = getFloatVectorFromString(node1.node().attribute("position1").value(), 3);
00298         ngl::Vector position1(tmp[0], tmp[1], tmp[2]);
00299 
00300         tmp = getFloatVectorFromString(node1.node().attribute("position2").value(), 3);
00301         ngl::Vector position2(tmp[0], tmp[1], tmp[2]);
00302 
00303         ngl::Real incrementAngle = node1.node().attribute("incrementAngle").as_float();
00304 
00305         ngl::Real initialAngle = node1.node().attribute("initialAngle").as_float();
00306 
00307         ngl::Real radius = node1.node().attribute("radius").as_float();
00308 
00309         ngl::Real moveable = node1.node().attribute("moveable").as_bool();
00310 
00311         tmp = getFloatVectorFromString(node1.node().attribute("colour").value(), 3);
00312         ngl::Colour colour(tmp[0], tmp[1], tmp[2]);
00313 
00314         //calculate orientation vector
00315         ngl::Vector orientationVector = position2 - position1;
00316 
00317         //calculate height half
00318         ngl::Real height = orientationVector.length() / 2.0;
00319 
00320         //normalise orientation vector
00321         orientationVector.normalize();
00322 
00323         //calculate centre position
00324         ngl::Vector centrePosition = position1 + (orientationVector * height);
00325 
00326         std::cout << "test Capsules : " << centrePosition << "\n";
00327 
00328         //create and add obstacle to list
00329         o_capsuleObstacleList.push_back
00330                 (
00331                     Capsule
00332                     (
00333                         Configuration::s_nextObstacleId--,
00334                         0,
00335                         centrePosition,
00336                         colour,
00337                         radius,
00338                         height,
00339                         orientationVector,
00340                         incrementAngle,
00341                         initialAngle,
00342                         moveable
00343                     )
00344                 );
00345     }
00346 
00347 }
00348 
00349 void Configuration::initialiseFluidSolver
00350                                 (
00351                                     ngl::Real& o_smoothingLength,
00352                                     std::vector<FluidParticle>& o_particleList,
00353                                     std::vector<FluidParticle>& o_hoseParticlePrototypeList,
00354                                     std::vector<FluidParticle>& o_hoseParticleList,
00355                                     ngl::Vector& o_centerOfHose,
00356                                     ngl::Vector& o_velocityOfHose,
00357                                     bool& o_drawHoseMarker,
00358                                     bool& o_hoseWaitUntilFirstHitBoundary,
00359                                     bool& o_hoseWaitUntilFirstHitRBD
00360                                 )
00361 {
00362     //load settings xml file
00363     pugi::xml_document doc;
00364     doc.load_file(s_settingsDoc.c_str());
00365 
00366     //load global settings here
00367     pugi::xpath_node_set node = doc.select_nodes("/Settings/FluidSolver");
00368 
00369     //read smoothing length
00370     o_smoothingLength = node.first().node().attribute("smoothingLength").as_float();
00371 
00372     //initially reserve space for maximum growth of particle list
00373     int initialReservedParticleCount =node.first().node().attribute("initialReservedParticleCount").as_int();
00374     o_particleList.reserve(initialReservedParticleCount);
00375 
00376     //tmp variable
00377     std::vector<ngl::Real> tmp;
00378 
00379     //get hose info
00380     node = doc.select_nodes("/Settings/FluidSolver/Hose");
00381 
00382     tmp = getFloatVectorFromString(node.first().node().attribute("center").value(), 3);
00383     o_centerOfHose = ngl::Vector(tmp[0], tmp[1], tmp[2]);
00384 
00385     o_hoseWaitUntilFirstHitBoundary = node.first().node().attribute("waitUntilHitBoundary").as_bool();
00386     o_hoseWaitUntilFirstHitRBD = node.first().node().attribute("waitUntilHitRBD").as_bool();
00387 
00388     o_drawHoseMarker = node.first().node().attribute("drawMarker").as_bool();
00389 
00390     std::string hoseMeshName = node.first().node().select_single_node("Obj").node().child_value();
00391     ngl::Obj hoseMesh(hoseMeshName);
00392 
00393     tmp = getFloatVectorFromString(node.first().node().select_single_node("Obj").node().attribute("center").value(), 3);
00394     ngl::Vector centerOfHoseMesh(tmp[0], tmp[1], tmp[2]);
00395 
00396     tmp = getFloatVectorFromString(node.first().node().select_single_node("Velocity").node().attribute("value").value(), 3);
00397     o_velocityOfHose = ngl::Vector(tmp[0], tmp[1], tmp[2]);
00398 
00399     for (int i = 0; i < hoseMesh.getNumVerts(); i++)
00400     {
00401         //create particle @ mesh vertices and add to hose particle list
00402         o_hoseParticleList.push_back
00403                 (
00404                         FluidParticle
00405                         (
00406                                 0,
00407                                 0,
00408                                 0,
00409                                 centerOfHoseMesh + hoseMesh.getVertexAtIndex(i)
00410                         )
00411                 );
00412     }
00413 
00414     //get a list of fluids
00415     node = doc.select_nodes("/Settings/FluidSolver/Fluid");
00416     for (pugi::xpath_node_set::const_iterator it = node.begin(); it != node.end(); ++it)
00417     {
00418         //get details for a fluid
00419         pugi::xpath_node node = *it;
00420 
00421         //get its active parameter
00422         bool isActive = node.node().attribute("active").as_bool();
00423 
00424         //skip this fluid if not active
00425         if (isActive)
00426         {
00427             //else, active fluid => go on creating and adding particles of fluid to particle list
00428 
00429             //read parameters
00430             ngl::Real volume = boost::lexical_cast<ngl::Real>(node.node().select_single_node("Volume").node().child_value());
00431 
00432             ngl::Real materialDensity = boost::lexical_cast<ngl::Real>(node.node().select_single_node("MaterialDensity").node().child_value());
00433 
00434             tmp = getFloatVectorFromString(node.node().select_single_node("Colour").node().attribute("value").value(), 3);
00435             ngl::Colour color(tmp[0], tmp[1], tmp[2]);
00436 
00437             std::string meshName = node.node().select_single_node("Obj").node().child_value();
00438             ngl::Obj mesh(meshName);
00439 
00440             tmp = getFloatVectorFromString(node.node().select_single_node("Obj").node().attribute("center").value(), 3);
00441             ngl::Vector centerOfMesh(tmp[0], tmp[1], tmp[2]);
00442 
00443             tmp = getFloatVectorFromString(node.node().select_single_node("Velocity").node().attribute("value").value(), 3);
00444             ngl::Vector velocity(tmp[0], tmp[1], tmp[2]);
00445 
00446             ngl::Real viscosityConstant = boost::lexical_cast<ngl::Real>(node.node().select_single_node("ViscosityConstant").node().child_value());
00447 
00448             ngl::Real gasConstant = boost::lexical_cast<ngl::Real>(node.node().select_single_node("GasConstant").node().child_value());
00449 
00450             ngl::Real surfaceTensionCoefficient = node.node().select_single_node("SurfaceTension").node().attribute("coefficient").as_float();
00451             ngl::Real surfaceTensionThreshold = node.node().select_single_node("SurfaceTension").node().attribute("threshold").as_float();
00452             ngl::Real surfaceColorCoefficient = node.node().select_single_node("SurfaceTension").node().attribute("color").as_float();
00453 
00454             ngl::Real interfaceTensionCoefficient = node.node().select_single_node("SurfaceInterface").node().attribute("coefficient").as_float();
00455             ngl::Real interfaceTensionThreshold = node.node().select_single_node("SurfaceInterface").node().attribute("threshold").as_float();
00456             ngl::Real interfaceColorCoefficient = node.node().select_single_node("SurfaceInterface").node().attribute("color").as_float();
00457 
00458             ngl::Real radius = boost::lexical_cast<ngl::Real>(node.node().select_single_node("Radius").node().child_value());
00459 
00460             std::string name = node.node().attribute("name").value();
00461 
00462             //calculate mass per particle
00463             int particleCount = mesh.getNumVerts();
00464             ngl::Real mass = materialDensity * (volume / ((ngl::Real)particleCount));
00465 
00466             std::cout << "Mesh : " << meshName << "\tparticle count : " << particleCount << "\tunit mass : " << mass << "\n";
00467 
00468             //create fluid particles from obj
00469             for (int i = 0; i < particleCount; i++)
00470             {
00471                 //create particle @ mesh vertices and add to particle list
00472                 o_particleList.push_back
00473                         (
00474                                 FluidParticle
00475                                 (
00476                                         Configuration::s_nextParticleId++,
00477                                         mass,
00478                                         materialDensity,
00479                                         centerOfMesh + mesh.getVertexAtIndex(i),
00480                                         velocity,
00481                                         viscosityConstant,
00482                                         gasConstant,
00483                                         surfaceTensionCoefficient,
00484                                         surfaceTensionThreshold,
00485                                         surfaceColorCoefficient,
00486                                         interfaceTensionCoefficient,
00487                                         interfaceTensionThreshold,
00488                                         interfaceColorCoefficient,
00489                                         color,
00490                                         radius,
00491                                         name
00492                                 )
00493                         );
00494             }
00495             std::cout << "Fluid : << " << name << "\tListSize : " << o_particleList.size() << "\n";
00496 
00497             //add a sample of this fluid's particle to hose prototype list
00498             o_hoseParticlePrototypeList.push_back
00499                     (
00500                             FluidParticle
00501                             (
00502                                     -1,
00503                                     mass,
00504                                     materialDensity,
00505                                     0,
00506                                     0,
00507                                     viscosityConstant,
00508                                     gasConstant,
00509                                     surfaceTensionCoefficient,
00510                                     surfaceTensionThreshold,
00511                                     surfaceColorCoefficient,
00512                                     interfaceTensionCoefficient,
00513                                     interfaceTensionThreshold,
00514                                     interfaceColorCoefficient,
00515                                     color,
00516                                     radius,
00517                                     name,
00518                                     o_hoseWaitUntilFirstHitBoundary,
00519                                     o_hoseWaitUntilFirstHitRBD
00520                             )
00521                     );
00522         }
00523     }
00524 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator