├── .gitignore ├── CMakeLists.txt ├── LICENSE.md ├── README.md └── src ├── aabb.cpp ├── aabb.h ├── anisotropicparticlemesher.cpp ├── anisotropicparticlemesher.h ├── array3d.h ├── arrayview3d.h ├── brick.h ├── c_bindings ├── aabb_c.h ├── cbindings.cpp ├── cbindings.h ├── config_c.cpp ├── cuboidfluidsource_c.cpp ├── diffuseparticle_c.h ├── fluidsimulation_c.cpp ├── fluidsimulationsavestate_c.cpp ├── fluidsource_c.cpp ├── gridindex_c.h ├── markerparticle_c.h ├── sphericalfluidsource_c.cpp ├── utils_c.cpp └── vector3_c.h ├── clscalarfield.cpp ├── clscalarfield.h ├── collision.cpp ├── collision.h ├── config.cpp ├── config.h.in ├── cuboidfluidsource.cpp ├── cuboidfluidsource.h ├── diffuseparticle.h ├── diffuseparticlesimulation.cpp ├── diffuseparticlesimulation.h ├── examples ├── cpp │ ├── example_dambreak.h │ ├── example_diffuse_inflow.h │ ├── example_export_particle_positions.h │ ├── example_gravity_field.h │ ├── example_hello_world.h │ ├── example_import_mesh_obstacle.h │ ├── example_inflow_outflow.h │ ├── example_lego_sphere_drop.h │ ├── example_save_load_state.h │ └── example_sphere_drop.h └── python │ ├── example_dambreak.py │ ├── example_diffuse_inflow.py │ ├── example_hello_world.py │ ├── example_inflow_outflow.py │ ├── example_lego_sphere_drop.py │ ├── example_save_load_state.py │ └── example_sphere_drop.py ├── fluidbrickgrid.cpp ├── fluidbrickgrid.h ├── fluidbrickgridsavestate.cpp ├── fluidbrickgridsavestate.h ├── fluidmaterialgrid.cpp ├── fluidmaterialgrid.h ├── fluidsimassert.h ├── fluidsimulation.cpp ├── fluidsimulation.h ├── fluidsimulationsavestate.cpp ├── fluidsimulationsavestate.h ├── fluidsource.cpp ├── fluidsource.h ├── fragmentedvector.h ├── grid3d.h ├── gridindexkeymap.cpp ├── gridindexkeymap.h ├── gridindexvector.cpp ├── gridindexvector.h ├── implicitpointprimitive.cpp ├── implicitpointprimitive.h ├── interpolation.cpp ├── interpolation.h ├── isotropicparticlemesher.cpp ├── isotropicparticlemesher.h ├── kernels ├── kernels.cpp ├── kernels.cpp.in ├── kernels.h ├── scalarfield.cl └── tricubicinterpolate.cl ├── levelset.cpp ├── levelset.h ├── logfile.cpp ├── logfile.h ├── macvelocityfield.cpp ├── macvelocityfield.h ├── main.cpp ├── main.h ├── markerparticle.h ├── mortonarray3d.h ├── particleadvector.cpp ├── particleadvector.h ├── polygonizer3d.cpp ├── polygonizer3d.h ├── pressuresolver.cpp ├── pressuresolver.h ├── pyfluid ├── __init__.py ├── aabb.py ├── array3d.py ├── config.py ├── fluidsimulation.py ├── fluidsimulationsavestate.py ├── fluidsource.py ├── gridindex.py ├── method_decorators.py ├── pybindings.py ├── pyfluid.py ├── utils.py └── vector3.py ├── render ├── blender_scripts │ ├── brick_texture_lookup_shader.osl │ ├── import_animation-basic.py │ ├── import_animation-brick.py │ ├── import_animation-diffuse.py │ └── import_animation-diffuse_particles_only.py └── brick_texture_packer │ ├── README.md │ ├── brick_texture_packer.cpp │ └── lodepng │ ├── README.md │ ├── lodepng.cpp │ └── lodepng.h ├── scalarfield.cpp ├── scalarfield.h ├── spatialpointgrid.cpp ├── spatialpointgrid.h ├── sphericalfluidsource.cpp ├── sphericalfluidsource.h ├── stopwatch.cpp ├── stopwatch.h ├── subdividedarray3d.h ├── triangle.h ├── trianglemesh.cpp ├── trianglemesh.h ├── turbulencefield.cpp ├── turbulencefield.h ├── utils.cpp ├── utils.h ├── vmath.cpp └── vmath.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.exe 3 | CMakeCache.txt 4 | CMakeFiles 5 | CMakeScripts 6 | Makefile 7 | cmake_install.cmake 8 | install_manifest.txt 9 | CTestTestfile.cmake -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.9) 2 | 3 | function(set_output_directories DIR) 4 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${DIR} PARENT_SCOPE) 5 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${DIR} PARENT_SCOPE) 6 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${DIR} PARENT_SCOPE) 7 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${DIR} PARENT_SCOPE) 8 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${DIR} PARENT_SCOPE) 9 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${DIR} PARENT_SCOPE) 10 | endfunction(set_output_directories) 11 | 12 | project(fluidsim) 13 | set(CMAKE_BUILD_TYPE Release) 14 | 15 | if (MSVC) 16 | add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_1_APIS -DNOMINMAX -D_CRT_SECURE_NO_WARNINGS) 17 | endif() 18 | 19 | if (APPLE) 20 | set(CMAKE_MACOSX_RPATH ON) 21 | endif() 22 | 23 | if (MSVC) 24 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /O2 /W4 /EHsc /wd4244") 25 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE") 26 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /LARGEADDRESSAWARE") 27 | elseif(MINGW) 28 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -std=c++11 -Wall") 29 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--enable-stdcall-fixup -Wl,--large-address-aware") 30 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--enable-stdcall-fixup -Wl,--large-address-aware") 31 | elseif(APPLE) 32 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -std=c++11 -Wall") 33 | else() 34 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -std=c++11 -Wall -fPIC") 35 | endif() 36 | 37 | find_package(OpenCL) 38 | 39 | if (NOT OpenCL_FOUND) 40 | message(FATAL_ERROR "Error: OpenCL was not found on your system.\nPlease install an OpenCL SDK specific to your GPU vender (AMD, NVIDIA, Intel, etc.) and try again.") 41 | endif() 42 | 43 | if (APPLE) 44 | set(CL_CPP_BINDINGS_DIR "${OpenCL_INCLUDE_DIRS}/Versions/A/Headers") 45 | else() 46 | set(CL_CPP_BINDINGS_DIR "${OpenCL_INCLUDE_DIRS}/CL") 47 | endif() 48 | 49 | if (NOT EXISTS "${CL_CPP_BINDINGS_DIR}/cl.hpp") 50 | message(FATAL_ERROR "Error: The OpenCL C++ bindings were not found on your system.\nPlease download the 'cl.hpp' header from https://www.khronos.org/registry/cl/ and place the file in the '${CL_CPP_BINDINGS_DIR}' directory and try again.") 51 | endif() 52 | 53 | include_directories(src ${OpenCL_INCLUDE_DIRS}) 54 | file(GLOB SOURCES "src/*.cpp" "src/c_bindings/*.cpp" "src/kernels/*.cpp") 55 | 56 | add_library(objects OBJECT ${SOURCES}) 57 | 58 | set(EXECUTABLE_DIR ${CMAKE_BINARY_DIR}/fluidsim) 59 | set_output_directories(${EXECUTABLE_DIR}) 60 | add_executable(fluidsim $) 61 | target_link_libraries(fluidsim ${OpenCL_LIBRARY}) 62 | 63 | set(PYTHON_MODULE_DIR ${CMAKE_BINARY_DIR}/fluidsim/pyfluid) 64 | set(PYTHON_MODULE_LIB_DIR ${CMAKE_BINARY_DIR}/fluidsim/pyfluid/lib) 65 | set_output_directories(${PYTHON_MODULE_LIB_DIR}) 66 | add_library(pyfluid SHARED $) 67 | target_link_libraries(pyfluid ${OpenCL_LIBRARY}) 68 | 69 | file(MAKE_DIRECTORY "${EXECUTABLE_DIR}/output/bakefiles") 70 | file(MAKE_DIRECTORY "${EXECUTABLE_DIR}/output/logs") 71 | file(MAKE_DIRECTORY "${EXECUTABLE_DIR}/output/savestates") 72 | file(MAKE_DIRECTORY "${EXECUTABLE_DIR}/output/temp") 73 | file(COPY "${CMAKE_SOURCE_DIR}/src/pyfluid/" DESTINATION "${PYTHON_MODULE_DIR}") 74 | file(COPY "${CMAKE_SOURCE_DIR}/src/examples/python/" DESTINATION "${PYTHON_MODULE_DIR}/examples") 75 | 76 | set(CONFIG_EXECUTABLE_DIR ${EXECUTABLE_DIR}) 77 | set(CONFIG_OUTPUT_DIR ${EXECUTABLE_DIR}/output) 78 | set(CONFIG_BAKEFILES_DIR ${EXECUTABLE_DIR}/output/bakefiles) 79 | set(CONFIG_LOGS_DIR ${EXECUTABLE_DIR}/output/logs) 80 | set(CONFIG_SAVESTATES_DIR ${EXECUTABLE_DIR}/output/savestates) 81 | set(CONFIG_TEMP_DIR ${EXECUTABLE_DIR}/output/temp) 82 | configure_file( 83 | "${PROJECT_SOURCE_DIR}/src/config.h.in" 84 | "${PROJECT_SOURCE_DIR}/src/config.h" 85 | ) 86 | 87 | file(READ "src/kernels/tricubicinterpolate.cl" TRICUBIC_INTERPOLATE_KERNEL_STRING) 88 | file(READ "src/kernels/scalarfield.cl" SCALAR_FIELD_KERNEL_STRING) 89 | set(TRICUBIC_INTERPOLATE_KERNEL_STRING ${TRICUBIC_INTERPOLATE_KERNEL_STRING}) 90 | set(SCALAR_FIELD_KERNEL_STRING ${SCALAR_FIELD_KERNEL_STRING}) 91 | configure_file( 92 | "${PROJECT_SOURCE_DIR}/src/kernels/kernels.cpp.in" 93 | "${PROJECT_SOURCE_DIR}/src/kernels/kernels.cpp" 94 | ) 95 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Ryan L. Guy 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgement in the product documentation would be 14 | appreciated but is not required. 15 | 2. Altered source versions must be plainly marked as such, and must not be 16 | misrepresented as being the original software. 17 | 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------------- /src/aabb.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef AABB_H 21 | #define AABB_H 22 | 23 | #include 24 | #include 25 | 26 | #include "triangle.h" 27 | #include "array3d.h" 28 | #include "vmath.h" 29 | 30 | class AABB 31 | { 32 | public: 33 | AABB(); 34 | AABB(double x, double y, double z, double width, double height, double depth); 35 | AABB(vmath::vec3 p, double width, double height, double depth); 36 | AABB(vmath::vec3 p1, vmath::vec3 p2); 37 | AABB(std::vector &points); 38 | AABB(Triangle t, std::vector &vertices); 39 | AABB(GridIndex g, double dx); 40 | ~AABB(); 41 | 42 | void expand(double v); 43 | bool isPointInside(vmath::vec3 p); 44 | bool isOverlappingTriangle(Triangle t, std::vector &vertices); 45 | bool isLineIntersecting(vmath::vec3 p1, vmath::vec3 p2); 46 | AABB getIntersection(AABB bbox); 47 | AABB getUnion(AABB bbox); 48 | 49 | vmath::vec3 getMinPoint(); 50 | vmath::vec3 getMaxPoint(); 51 | vmath::vec3 getNearestPointInsideAABB(vmath::vec3 p, double eps); 52 | vmath::vec3 getNearestPointInsideAABB(vmath::vec3 p); 53 | 54 | vmath::vec3 position; 55 | double width = 0.0; 56 | double height = 0.0; 57 | double depth = 0.0; 58 | 59 | private: 60 | bool _axisTestX01(vmath::vec3 v0, vmath::vec3 v2, 61 | double a, double b, double fa, double fb); 62 | bool _axisTestX2(vmath::vec3 v0, vmath::vec3 v1, 63 | double a, double b, double fa, double fb); 64 | bool _axisTestY02(vmath::vec3 v0, vmath::vec3 v2, 65 | double a, double b, double fa, double fb); 66 | bool _axisTestY1(vmath::vec3 v0, vmath::vec3 v1, 67 | double a, double b, double fa, double fb); 68 | bool _axisTestZ12(vmath::vec3 v1, vmath::vec3 v2, 69 | double a, double b, double fa, double fb); 70 | bool _axisTestZ0(vmath::vec3 v0, vmath::vec3 v1, 71 | double a, double b, double fa, double fb); 72 | void _findminmax(double v0, double v1, double v2, double *min, double *max); 73 | bool _planeBoxOverlap(vmath::vec3 normal, vmath::vec3 vert); 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/brick.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef BRICK_H 21 | #define BRICK_H 22 | 23 | struct Brick { 24 | float intensity = 0.0f; 25 | bool isActive = false; 26 | 27 | Brick() : intensity(0.0f), 28 | isActive(false) {} 29 | 30 | Brick(float i) : intensity(i), 31 | isActive(false) {} 32 | }; 33 | 34 | #endif -------------------------------------------------------------------------------- /src/c_bindings/aabb_c.h: -------------------------------------------------------------------------------- 1 | #ifndef AABB_T_H 2 | #define AABB_T_H 3 | 4 | #include "vector3_c.h" 5 | 6 | typedef struct AABB_t { 7 | Vector3_t position; 8 | float width; 9 | float height; 10 | float depth; 11 | } AABB_t; 12 | 13 | #endif -------------------------------------------------------------------------------- /src/c_bindings/cbindings.cpp: -------------------------------------------------------------------------------- 1 | #include "cbindings.h" 2 | 3 | #ifdef _WIN32 4 | #define EXPORTDLL __declspec(dllexport) 5 | #else 6 | #define EXPORTDLL 7 | #endif 8 | 9 | namespace CBindings { 10 | 11 | int SUCCESS = 1; 12 | int FAIL = 0; 13 | char CBINDINGS_ERROR_MESSAGE[4096]; 14 | 15 | void set_error_message(std::exception &ex) { 16 | std::string msg = ex.what(); 17 | msg.copy(CBINDINGS_ERROR_MESSAGE, msg.length(), 0); 18 | CBINDINGS_ERROR_MESSAGE[msg.length()] = '\0'; 19 | } 20 | 21 | char* get_error_message() { 22 | return CBINDINGS_ERROR_MESSAGE; 23 | } 24 | 25 | Vector3_t to_struct(vmath::vec3 v) { 26 | return Vector3_t{ v.x, v.y, v.z}; 27 | } 28 | 29 | vmath::vec3 to_class(Vector3_t v) { 30 | return vmath::vec3(v.x, v.y, v.z); 31 | } 32 | 33 | AABB_t to_struct(AABB b) { 34 | Vector3_t cpos = to_struct(b.position); 35 | return AABB_t{ cpos, 36 | (float)b.width, 37 | (float)b.height, 38 | (float)b.depth }; 39 | } 40 | 41 | AABB to_class(AABB_t b) { 42 | return AABB(b.position.x, b.position.y, b.position.z, 43 | b.width, b.height, b.depth); 44 | } 45 | 46 | MarkerParticle_t to_struct(MarkerParticle p) { 47 | Vector3_t pos = to_struct(p.position); 48 | Vector3_t vel = to_struct(p.velocity); 49 | return MarkerParticle_t{ pos, vel }; 50 | } 51 | 52 | MarkerParticle to_class(MarkerParticle_t p) { 53 | vmath::vec3 pos = to_class(p.position); 54 | vmath::vec3 vel = to_class(p.velocity); 55 | return MarkerParticle(pos, vel); 56 | } 57 | 58 | DiffuseParticle_t to_struct(DiffuseParticle p) { 59 | Vector3_t pos = to_struct(p.position); 60 | Vector3_t vel = to_struct(p.velocity); 61 | return DiffuseParticle_t{ pos, vel, p.lifetime, (char)p.type }; 62 | } 63 | 64 | DiffuseParticle to_class(DiffuseParticle_t p) { 65 | vmath::vec3 pos = to_class(p.position); 66 | vmath::vec3 vel = to_class(p.velocity); 67 | 68 | DiffuseParticle dp(pos, vel, p.lifetime); 69 | dp.type = (DiffuseParticleType)p.type; 70 | return dp; 71 | } 72 | 73 | 74 | } 75 | 76 | extern "C" { 77 | EXPORTDLL char* CBindings_get_error_message() { 78 | return CBindings::get_error_message(); 79 | } 80 | } -------------------------------------------------------------------------------- /src/c_bindings/cbindings.h: -------------------------------------------------------------------------------- 1 | #ifndef CBINDINGS_H 2 | #define CBINDINGS_H 3 | 4 | #include 5 | #include 6 | 7 | #include "../vmath.h" 8 | #include "../aabb.h" 9 | #include "vector3_c.h" 10 | #include "aabb_c.h" 11 | #include "../markerparticle.h" 12 | #include "../diffuseparticle.h" 13 | #include "markerparticle_c.h" 14 | #include "diffuseparticle_c.h" 15 | 16 | namespace CBindings { 17 | 18 | extern int SUCCESS; 19 | extern int FAIL; 20 | extern char CBINDINGS_ERROR_MESSAGE[4096]; 21 | 22 | extern void set_error_message(std::exception &ex); 23 | extern char* get_error_message(); 24 | 25 | template 26 | void safe_execute_method_void_0param(CLASS *obj, void (CLASS::*funcptr)(void), int *err) { 27 | *err = SUCCESS; 28 | try { 29 | (obj->*funcptr)(); 30 | } catch (std::exception &ex) { 31 | CBindings::set_error_message(ex); 32 | *err = FAIL; 33 | } 34 | } 35 | 36 | template 37 | T safe_execute_method_ret_0param(CLASS *obj, T (CLASS::*funcptr)(void), int *err) { 38 | *err = SUCCESS; 39 | T result = T(); 40 | try { 41 | result = (obj->*funcptr)(); 42 | } catch (std::exception &ex) { 43 | CBindings::set_error_message(ex); 44 | *err = FAIL; 45 | } 46 | 47 | return result; 48 | } 49 | 50 | template 51 | void safe_execute_method_void_1param(CLASS *obj, void (CLASS::*funcptr)(T), T param, int *err) { 52 | *err = SUCCESS; 53 | try { 54 | (obj->*funcptr)(param); 55 | } catch (std::exception &ex) { 56 | CBindings::set_error_message(ex); 57 | *err = FAIL; 58 | } 59 | } 60 | 61 | template 62 | RT safe_execute_method_ret_1param(CLASS *obj, RT (CLASS::*funcptr)(T), T param, int *err) { 63 | *err = SUCCESS; 64 | RT result = RT(); 65 | try { 66 | result = (obj->*funcptr)(param); 67 | } catch (std::exception &ex) { 68 | CBindings::set_error_message(ex); 69 | *err = FAIL; 70 | } 71 | 72 | return result; 73 | } 74 | 75 | template 76 | void safe_execute_method_void_2param(CLASS *obj, 77 | void (CLASS::*funcptr)(T, T), 78 | T param1, T param2, int *err) { 79 | *err = SUCCESS; 80 | try { 81 | (obj->*funcptr)(param1, param2); 82 | } catch (std::exception &ex) { 83 | CBindings::set_error_message(ex); 84 | *err = FAIL; 85 | } 86 | } 87 | 88 | template 89 | RT safe_execute_method_ret_2param(CLASS *obj, 90 | RT (CLASS::*funcptr)(T, T), 91 | T param1, T param2, int *err) { 92 | RT result = RT(); 93 | *err = SUCCESS; 94 | try { 95 | result = (obj->*funcptr)(param1, param2); 96 | } catch (std::exception &ex) { 97 | CBindings::set_error_message(ex); 98 | *err = FAIL; 99 | } 100 | 101 | return result; 102 | } 103 | 104 | template 105 | void safe_execute_method_void_3param(CLASS *obj, 106 | void (CLASS::*funcptr)(T, T, T), 107 | T param1, T param2, T param3, int *err) { 108 | *err = SUCCESS; 109 | try { 110 | (obj->*funcptr)(param1, param2, param3); 111 | } catch (std::exception &ex) { 112 | CBindings::set_error_message(ex); 113 | *err = FAIL; 114 | } 115 | } 116 | 117 | template 118 | RT safe_execute_method_ret_3param(CLASS *obj, 119 | RT (CLASS::*funcptr)(T, T, T), 120 | T param1, T param2, T param3, int *err) { 121 | RT result = RT(); 122 | *err = SUCCESS; 123 | try { 124 | result = (obj->*funcptr)(param1, param2, param3); 125 | } catch (std::exception &ex) { 126 | CBindings::set_error_message(ex); 127 | *err = FAIL; 128 | } 129 | 130 | return result; 131 | } 132 | 133 | Vector3_t to_struct(vmath::vec3 v); 134 | vmath::vec3 to_class(Vector3_t v); 135 | AABB_t to_struct(AABB b); 136 | AABB to_class(AABB_t v); 137 | MarkerParticle_t to_struct(MarkerParticle p); 138 | MarkerParticle to_class(MarkerParticle_t p); 139 | DiffuseParticle_t to_struct(DiffuseParticle p); 140 | DiffuseParticle to_class(DiffuseParticle_t p); 141 | 142 | } 143 | 144 | #endif -------------------------------------------------------------------------------- /src/c_bindings/config_c.cpp: -------------------------------------------------------------------------------- 1 | #include "../config.h" 2 | 3 | #include 4 | 5 | #ifdef _WIN32 6 | #define EXPORTDLL __declspec(dllexport) 7 | #else 8 | #define EXPORTDLL 9 | #endif 10 | 11 | extern "C" { 12 | 13 | EXPORTDLL void Config_get_executable_directory(char *dir) { 14 | std::string dirstr = Config::getExecutableDirectory(); 15 | memcpy(dir, &dirstr[0], dirstr.size()); 16 | dir[dirstr.size()] = '\0'; 17 | } 18 | 19 | EXPORTDLL void Config_get_output_directory(char *dir) { 20 | std::string dirstr = Config::getOutputDirectory(); 21 | memcpy(dir, &dirstr[0], dirstr.size()); 22 | dir[dirstr.size()] = '\0'; 23 | } 24 | 25 | EXPORTDLL void Config_get_bakefiles_directory(char *dir) { 26 | std::string dirstr = Config::getBakefilesDirectory(); 27 | memcpy(dir, &dirstr[0], dirstr.size()); 28 | dir[dirstr.size()] = '\0'; 29 | } 30 | 31 | EXPORTDLL void Config_get_logs_directory(char *dir) { 32 | std::string dirstr = Config::getLogsDirectory(); 33 | memcpy(dir, &dirstr[0], dirstr.size()); 34 | dir[dirstr.size()] = '\0'; 35 | } 36 | 37 | EXPORTDLL void Config_get_savestates_directory(char *dir) { 38 | std::string dirstr = Config::getSavestatesDirectory(); 39 | memcpy(dir, &dirstr[0], dirstr.size()); 40 | dir[dirstr.size()] = '\0'; 41 | } 42 | 43 | EXPORTDLL void Config_get_temp_directory(char *dir) { 44 | std::string dirstr = Config::getTempDirectory(); 45 | memcpy(dir, &dirstr[0], dirstr.size()); 46 | dir[dirstr.size()] = '\0'; 47 | } 48 | 49 | EXPORTDLL void Config_set_output_directory(char *dir) { 50 | Config::setOutputDirectory(std::string(dir)); 51 | } 52 | 53 | EXPORTDLL void Config_set_bakefiles_directory(char *dir) { 54 | Config::setBakefilesDirectory(std::string(dir)); 55 | } 56 | 57 | EXPORTDLL void Config_set_logs_directory(char *dir) { 58 | Config::setLogsDirectory(std::string(dir)); 59 | } 60 | 61 | EXPORTDLL void Config_set_savestates_directory(char *dir) { 62 | Config::setSavestatesDirectory(std::string(dir)); 63 | } 64 | 65 | EXPORTDLL void Config_set_temp_directory(char *dir) { 66 | Config::setTempDirectory(std::string(dir)); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/c_bindings/cuboidfluidsource_c.cpp: -------------------------------------------------------------------------------- 1 | #include "../cuboidfluidsource.h" 2 | #include "cbindings.h" 3 | #include "vector3_c.h" 4 | #include "aabb_c.h" 5 | 6 | #ifdef _WIN32 7 | #define EXPORTDLL __declspec(dllexport) 8 | #else 9 | #define EXPORTDLL 10 | #endif 11 | 12 | extern "C" { 13 | EXPORTDLL CuboidFluidSource* CuboidFluidSource_new(AABB_t cbbox, 14 | Vector3_t cvelocity, 15 | int *err) { 16 | AABB bbox(cbbox.position.x, cbbox.position.y, cbbox.position.z, 17 | cbbox.width, cbbox.height, cbbox.depth); 18 | vmath::vec3 v(cvelocity.x, cvelocity.y, cvelocity.z); 19 | 20 | CuboidFluidSource *source = nullptr; 21 | *err = CBindings::SUCCESS; 22 | try { 23 | source = new CuboidFluidSource(bbox, v); 24 | } catch (std::exception &ex) { 25 | CBindings::set_error_message(ex); 26 | *err = CBindings::FAIL; 27 | } 28 | 29 | return source; 30 | } 31 | 32 | EXPORTDLL void CuboidFluidSource_destroy(CuboidFluidSource* obj) { 33 | delete obj; 34 | } 35 | 36 | EXPORTDLL double CuboidFluidSource_get_width(CuboidFluidSource* obj, 37 | int *err) { 38 | return CBindings::safe_execute_method_ret_0param( 39 | obj, &CuboidFluidSource::getWidth, err 40 | ); 41 | } 42 | 43 | EXPORTDLL void CuboidFluidSource_set_width(CuboidFluidSource* obj, 44 | double width, int *err) { 45 | CBindings::safe_execute_method_void_1param( 46 | obj, &CuboidFluidSource::setWidth, width, err 47 | ); 48 | } 49 | 50 | EXPORTDLL double CuboidFluidSource_get_height(CuboidFluidSource* obj, 51 | int *err) { 52 | return CBindings::safe_execute_method_ret_0param( 53 | obj, &CuboidFluidSource::getHeight, err 54 | ); 55 | } 56 | 57 | EXPORTDLL void CuboidFluidSource_set_height(CuboidFluidSource* obj, 58 | double height, int *err) { 59 | CBindings::safe_execute_method_void_1param( 60 | obj, &CuboidFluidSource::setHeight, height, err 61 | ); 62 | } 63 | 64 | EXPORTDLL double CuboidFluidSource_get_depth(CuboidFluidSource* obj, 65 | int *err) { 66 | return CBindings::safe_execute_method_ret_0param( 67 | obj, &CuboidFluidSource::getDepth, err 68 | ); 69 | } 70 | 71 | EXPORTDLL void CuboidFluidSource_set_depth(CuboidFluidSource* obj, 72 | double depth, int *err) { 73 | CBindings::safe_execute_method_void_1param( 74 | obj, &CuboidFluidSource::setDepth, depth, err 75 | ); 76 | } 77 | 78 | EXPORTDLL void CuboidFluidSource_set_AABB(CuboidFluidSource* obj, 79 | AABB_t cbbox, int *err) { 80 | AABB bbox = CBindings::to_class(cbbox); 81 | CBindings::safe_execute_method_void_1param( 82 | obj, &CuboidFluidSource::setAABB, bbox, err 83 | ); 84 | } 85 | 86 | EXPORTDLL Vector3_t CuboidFluidSource_get_center(CuboidFluidSource* obj, 87 | int *err) { 88 | vmath::vec3 cpos = CBindings::safe_execute_method_ret_0param( 89 | obj, &CuboidFluidSource::getCenter, err 90 | ); 91 | return CBindings::to_struct(cpos); 92 | } 93 | 94 | EXPORTDLL void CuboidFluidSource_set_center(CuboidFluidSource* obj, 95 | Vector3_t cpos, int *err) { 96 | vmath::vec3 c = CBindings::to_class(cpos); 97 | CBindings::safe_execute_method_void_1param( 98 | obj, &CuboidFluidSource::setCenter, c, err 99 | ); 100 | } 101 | 102 | EXPORTDLL void CuboidFluidSource_expand(CuboidFluidSource* obj, 103 | double val, int *err) { 104 | CBindings::safe_execute_method_void_1param( 105 | obj, &CuboidFluidSource::expand, val, err 106 | ); 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/c_bindings/diffuseparticle_c.h: -------------------------------------------------------------------------------- 1 | #ifndef DIFFUSEPARTICLE_T_H 2 | #define DIFFUSEPARTICLE_T_H 3 | 4 | #include "vector3_c.h" 5 | 6 | typedef struct DiffuseParticle_t { 7 | Vector3_t position; 8 | Vector3_t velocity; 9 | float lifetime; 10 | char type; 11 | } DiffuseParticle_t; 12 | 13 | #endif -------------------------------------------------------------------------------- /src/c_bindings/fluidsource_c.cpp: -------------------------------------------------------------------------------- 1 | #include "../fluidsource.h" 2 | #include "cbindings.h" 3 | #include "vector3_c.h" 4 | #include "aabb_c.h" 5 | 6 | #ifdef _WIN32 7 | #define EXPORTDLL __declspec(dllexport) 8 | #else 9 | #define EXPORTDLL 10 | #endif 11 | 12 | extern "C" { 13 | 14 | EXPORTDLL Vector3_t FluidSource_get_position(FluidSource* obj, int *err) { 15 | vmath::vec3 pos = CBindings::safe_execute_method_ret_0param( 16 | obj, &FluidSource::getPosition, err 17 | ); 18 | return CBindings::to_struct(pos); 19 | } 20 | 21 | EXPORTDLL void FluidSource_set_position(FluidSource* obj, 22 | Vector3_t cpos, int *err) { 23 | vmath::vec3 p = CBindings::to_class(cpos); 24 | CBindings::safe_execute_method_void_1param( 25 | obj, &FluidSource::setPosition, p, err 26 | ); 27 | } 28 | 29 | EXPORTDLL Vector3_t FluidSource_get_velocity(FluidSource* obj, int *err) { 30 | vmath::vec3 v = CBindings::safe_execute_method_ret_0param( 31 | obj, &FluidSource::getVelocity, err 32 | ); 33 | return CBindings::to_struct(v); 34 | } 35 | 36 | EXPORTDLL void FluidSource_set_velocity(FluidSource* obj, 37 | Vector3_t cvel, int *err) { 38 | vmath::vec3 v = CBindings::to_class(cvel); 39 | CBindings::safe_execute_method_void_1param( 40 | obj, &FluidSource::setVelocity, v, err 41 | ); 42 | } 43 | 44 | EXPORTDLL Vector3_t FluidSource_get_direction(FluidSource* obj, int *err) { 45 | vmath::vec3 d = CBindings::safe_execute_method_ret_0param( 46 | obj, &FluidSource::getDirection, err 47 | ); 48 | return CBindings::to_struct(d); 49 | } 50 | 51 | EXPORTDLL void FluidSource_set_direction(FluidSource* obj, 52 | Vector3_t cdir, int *err) { 53 | vmath::vec3 d = CBindings::to_class(cdir); 54 | CBindings::safe_execute_method_void_1param( 55 | obj, &FluidSource::setDirection, d, err 56 | ); 57 | } 58 | 59 | EXPORTDLL AABB_t FluidSource_get_AABB(FluidSource* obj, int *err) { 60 | AABB bbox = CBindings::safe_execute_method_ret_0param( 61 | obj, &FluidSource::getAABB, err 62 | ); 63 | return CBindings::to_struct(bbox); 64 | } 65 | 66 | EXPORTDLL int FluidSource_contains_point(FluidSource* obj, 67 | Vector3_t cpos, int *err) { 68 | vmath::vec3 p = CBindings::to_class(cpos); 69 | return CBindings::safe_execute_method_ret_1param( 70 | obj, &FluidSource::containsPoint, p, err 71 | ); 72 | } 73 | 74 | EXPORTDLL int FluidSource_is_inflow(FluidSource* obj, int *err) { 75 | return CBindings::safe_execute_method_ret_0param( 76 | obj, &FluidSource::isInflow, err 77 | ); 78 | } 79 | 80 | EXPORTDLL int FluidSource_is_outflow(FluidSource* obj, int *err) { 81 | return CBindings::safe_execute_method_ret_0param( 82 | obj, &FluidSource::isOutflow, err 83 | ); 84 | } 85 | 86 | EXPORTDLL void FluidSource_set_as_inflow(FluidSource* obj, int *err) { 87 | CBindings::safe_execute_method_void_0param( 88 | obj, &FluidSource::setAsInflow, err 89 | ); 90 | } 91 | 92 | EXPORTDLL void FluidSource_set_as_outflow(FluidSource* obj, int *err) { 93 | CBindings::safe_execute_method_void_0param( 94 | obj, &FluidSource::setAsOutflow, err 95 | ); 96 | } 97 | 98 | EXPORTDLL void FluidSource_activate(FluidSource* obj, int *err) { 99 | CBindings::safe_execute_method_void_0param( 100 | obj, &FluidSource::activate, err 101 | ); 102 | } 103 | 104 | EXPORTDLL void FluidSource_deactivate(FluidSource* obj, int *err) { 105 | CBindings::safe_execute_method_void_0param( 106 | obj, &FluidSource::deactivate, err 107 | ); 108 | } 109 | 110 | EXPORTDLL int FluidSource_is_active(FluidSource* obj, int *err) { 111 | return CBindings::safe_execute_method_ret_0param( 112 | obj, &FluidSource::isActive, err 113 | ); 114 | } 115 | 116 | EXPORTDLL int FluidSource_get_id(FluidSource* obj, int *err) { 117 | return CBindings::safe_execute_method_ret_0param( 118 | obj, &FluidSource::getID, err 119 | ); 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/c_bindings/gridindex_c.h: -------------------------------------------------------------------------------- 1 | #ifndef GRIDINDEX_T_H 2 | #define GRIDINDEX_T_H 3 | 4 | typedef struct GridIndex_t { 5 | int i; 6 | int j; 7 | int k; 8 | } GridIndex_t; 9 | 10 | #endif -------------------------------------------------------------------------------- /src/c_bindings/markerparticle_c.h: -------------------------------------------------------------------------------- 1 | #ifndef MARKERPARTICLE_T_H 2 | #define MARKERPARTICLE_T_H 3 | 4 | #include "vector3_c.h" 5 | 6 | typedef struct MarkerParticle_t { 7 | Vector3_t position; 8 | Vector3_t velocity; 9 | } MarkerParticle_t; 10 | 11 | #endif -------------------------------------------------------------------------------- /src/c_bindings/sphericalfluidsource_c.cpp: -------------------------------------------------------------------------------- 1 | #include "../sphericalfluidsource.h" 2 | #include "cbindings.h" 3 | #include "vector3_c.h" 4 | #include "aabb_c.h" 5 | 6 | #ifdef _WIN32 7 | #define EXPORTDLL __declspec(dllexport) 8 | #else 9 | #define EXPORTDLL 10 | #endif 11 | 12 | extern "C" { 13 | EXPORTDLL SphericalFluidSource* SphericalFluidSource_new(Vector3_t cpos, 14 | double radius, 15 | Vector3_t cvelocity, 16 | int *err) { 17 | vmath::vec3 p(cpos.x, cpos.y, cpos.z); 18 | vmath::vec3 v(cvelocity.x, cvelocity.y, cvelocity.z); 19 | 20 | SphericalFluidSource *source = nullptr; 21 | *err = CBindings::SUCCESS; 22 | try { 23 | source = new SphericalFluidSource(p, radius, v); 24 | } catch (std::exception &ex) { 25 | CBindings::set_error_message(ex); 26 | *err = CBindings::FAIL; 27 | } 28 | 29 | return source; 30 | } 31 | 32 | EXPORTDLL void SphericalFluidSource_destroy(SphericalFluidSource* obj) { 33 | delete obj; 34 | } 35 | 36 | EXPORTDLL double SphericalFluidSource_get_radius(SphericalFluidSource* obj, 37 | int *err) { 38 | return CBindings::safe_execute_method_ret_0param( 39 | obj, &SphericalFluidSource::getRadius, err 40 | ); 41 | } 42 | 43 | EXPORTDLL void SphericalFluidSource_set_radius(SphericalFluidSource* obj, 44 | double radius, int *err) { 45 | CBindings::safe_execute_method_void_1param( 46 | obj, &SphericalFluidSource::setRadius, radius, err 47 | ); 48 | } 49 | 50 | EXPORTDLL void SphericalFluidSource_expand(SphericalFluidSource* obj, 51 | double val, int *err) { 52 | CBindings::safe_execute_method_void_1param( 53 | obj, &SphericalFluidSource::expand, val, err 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/c_bindings/utils_c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../utils.h" 5 | 6 | #include "cbindings.h" 7 | #include "gridindex_c.h" 8 | 9 | #ifdef _WIN32 10 | #define EXPORTDLL __declspec(dllexport) 11 | #else 12 | #define EXPORTDLL 13 | #endif 14 | 15 | extern "C" { 16 | 17 | EXPORTDLL int utils_get_triangle_mesh_cells_storage_size( 18 | utils::TriangleMesh_t *mesh_data, double dx, int *err) { 19 | 20 | TriangleMesh mesh; 21 | utils::structToTriangleMesh(*mesh_data, mesh); 22 | AABB bbox(mesh.vertices); 23 | 24 | GridIndex goffset = Grid3d::positionToGridIndex(bbox.position, dx); 25 | vmath::vec3 offset = Grid3d::GridIndexToPosition(goffset, dx); 26 | 27 | bbox.position -= offset; 28 | int inf = std::numeric_limits::max(); 29 | GridIndex gmin, gmax; 30 | Grid3d::getGridIndexBounds(bbox, dx, inf, inf, inf, &gmin, &gmax); 31 | int size = (gmax.i + 1) * (gmax.j + 1) * (gmax.k + 1); 32 | 33 | *err = CBindings::SUCCESS; 34 | return size; 35 | } 36 | 37 | EXPORTDLL void utils_get_triangle_mesh_cells( 38 | utils::TriangleMesh_t *mesh_data, double dx, 39 | GridIndex_t *output, int outsize, int *numcells, int *err) { 40 | 41 | TriangleMesh mesh; 42 | utils::structToTriangleMesh(*mesh_data, mesh); 43 | AABB bbox(mesh.vertices); 44 | 45 | GridIndex goffset = Grid3d::positionToGridIndex(bbox.position, dx); 46 | vmath::vec3 offset = Grid3d::GridIndexToPosition(goffset, dx); 47 | mesh.translate(-offset); 48 | bbox.position -= offset; 49 | 50 | int inf = std::numeric_limits::max(); 51 | GridIndex gmin, gmax; 52 | Grid3d::getGridIndexBounds(bbox, dx, inf, inf, inf, &gmin, &gmax); 53 | 54 | std::vector cells; 55 | cells.reserve(outsize); 56 | utils::getCellsInsideTriangleMesh( 57 | mesh, gmax.i + 1, gmax.j + 1, gmax.k + 1, dx, cells 58 | ); 59 | 60 | GridIndex g; 61 | for (unsigned int i = 0; i < cells.size(); i++) { 62 | g = cells[i]; 63 | output[i] = GridIndex_t{ g.i + goffset.i, 64 | g.j + goffset.j, 65 | g.k + goffset.k }; 66 | } 67 | 68 | *numcells = (int)cells.size(); 69 | *err = CBindings::SUCCESS; 70 | } 71 | 72 | EXPORTDLL void utils_get_triangle_mesh_cells_subd2( 73 | utils::TriangleMesh_t *mesh_data, double dx, 74 | GridIndex_t *output_cells, unsigned char *output_cell_masks, 75 | int outsize, int *numcells, int *err) { 76 | 77 | TriangleMesh mesh; 78 | utils::structToTriangleMesh(*mesh_data, mesh); 79 | AABB bbox(mesh.vertices); 80 | 81 | GridIndex goffset = Grid3d::positionToGridIndex(bbox.position, dx); 82 | vmath::vec3 offset = Grid3d::GridIndexToPosition(goffset, dx); 83 | mesh.translate(-offset); 84 | bbox.position -= offset; 85 | 86 | int inf = std::numeric_limits::max(); 87 | GridIndex gmin, gmax; 88 | Grid3d::getGridIndexBounds(bbox, dx, inf, inf, inf, &gmin, &gmax); 89 | 90 | std::vector cells; 91 | std::vector cell_masks; 92 | cells.reserve(outsize); 93 | cell_masks.reserve(outsize); 94 | 95 | utils::getCellsInsideTriangleMeshSubd2( 96 | mesh, gmax.i + 1, gmax.j + 1, gmax.k + 1, dx, cells, cell_masks 97 | ); 98 | 99 | GridIndex g; 100 | for (unsigned int i = 0; i < cells.size(); i++) { 101 | g = cells[i]; 102 | output_cells[i] = GridIndex_t{ g.i + goffset.i, 103 | g.j + goffset.j, 104 | g.k + goffset.k }; 105 | output_cell_masks[i] = cell_masks[i]; 106 | } 107 | 108 | *numcells = cells.size(); 109 | *err = CBindings::SUCCESS; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/c_bindings/vector3_c.h: -------------------------------------------------------------------------------- 1 | #ifndef VECTOR3_T_H 2 | #define VECTOR3_T_H 3 | 4 | typedef struct Vector3_t { 5 | float x; 6 | float y; 7 | float z; 8 | } Vector3_t; 9 | 10 | #endif -------------------------------------------------------------------------------- /src/collision.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef COLLISION_H 21 | #define COLLISION_H 22 | 23 | #include 24 | #include 25 | 26 | #include "vmath.h" 27 | #include "grid3d.h" 28 | #include "fluidmaterialgrid.h" 29 | #include "aabb.h" 30 | #include "fluidsimassert.h" 31 | 32 | namespace Collision { 33 | 34 | double _clamp(double v, double min, double max); 35 | 36 | // method adapted from: 37 | // http://www.lighthouse3d.com/tutorials/maths/ray-triangle-intersection/ 38 | extern bool rayIntersectsTriangle(vmath::vec3 p, vmath::vec3 dir, 39 | vmath::vec3 v0, vmath::vec3 v1, vmath::vec3 v2, 40 | vmath::vec3 *collision, double *u, double *v); 41 | 42 | extern bool lineIntersectsTriangle(vmath::vec3 p, vmath::vec3 dir, 43 | vmath::vec3 v0, vmath::vec3 v1, vmath::vec3 v2, 44 | vmath::vec3 *collision, double *u, double *v); 45 | 46 | extern bool rayIntersectsPlane(vmath::vec3 p0, vmath::vec3 dir, 47 | vmath::vec3 planePoint, vmath::vec3 planeNormal, 48 | vmath::vec3 *collision); 49 | 50 | extern bool lineIntersectsPlane(vmath::vec3 p0, vmath::vec3 dir, 51 | vmath::vec3 planePoint, vmath::vec3 planeNormal, 52 | vmath::vec3 *collision); 53 | 54 | 55 | // method adapted from: 56 | // http://www.geometrictools.com/Documentation/DistancePoint3Triangle3.pdf 57 | extern vmath::vec3 findClosestPointOnTriangle(vmath::vec3 p0, vmath::vec3 v0, vmath::vec3 v1, vmath::vec3 v2); 58 | 59 | 60 | extern bool rayIntersectsTriangle(vmath::vec3 p, vmath::vec3 dir, 61 | vmath::vec3 v0, vmath::vec3 v1, vmath::vec3 v2); 62 | 63 | extern bool rayIntersectsTriangle(vmath::vec3 p, vmath::vec3 dir, 64 | vmath::vec3 v0, vmath::vec3 v1, vmath::vec3 v2, vmath::vec3 *collision); 65 | 66 | extern bool lineIntersectsTriangle(vmath::vec3 p, vmath::vec3 dir, 67 | vmath::vec3 v0, vmath::vec3 v1, vmath::vec3 v2); 68 | 69 | extern bool lineIntersectsTriangle(vmath::vec3 p, vmath::vec3 dir, 70 | vmath::vec3 v0, vmath::vec3 v1, vmath::vec3 v2, vmath::vec3 *collision); 71 | 72 | extern bool rayIntersectsPlane(vmath::vec3 p0, vmath::vec3 dir, 73 | vmath::vec3 planePoint, vmath::vec3 planeNormal); 74 | 75 | extern bool lineIntersectsPlane(vmath::vec3 p0, vmath::vec3 dir, 76 | vmath::vec3 planePoint, vmath::vec3 planeNormal); 77 | 78 | extern vmath::vec3 getTriangleCentroid(vmath::vec3 p0, vmath::vec3 p1, vmath::vec3 p2); 79 | extern vmath::vec3 getTriangleNormal(vmath::vec3 p0, vmath::vec3 p1, vmath::vec3 p2); 80 | 81 | extern bool getLineSegmentVoxelIntersection(vmath::vec3 p0, 82 | vmath::vec3 p1, 83 | double dx, 84 | FluidMaterialGrid &grid, 85 | GridIndex *voxel); 86 | 87 | extern bool rayIntersectsAABB(vmath::vec3 p0, vmath::vec3 dir, 88 | AABB &bbox, vmath::vec3 *collision); 89 | 90 | extern bool sphereIntersectsAABB(vmath::vec3 p, double r, AABB bbox); 91 | } 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /src/config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "config.h" 21 | 22 | namespace Config { 23 | std::string executableDirectory = CONFIG_EXECUTABLE_DIR; 24 | std::string outputDirectory = CONFIG_OUTPUT_DIR; 25 | std::string bakefilesDirectory = CONFIG_BAKEFILES_DIR; 26 | std::string logsDirectory = CONFIG_LOGS_DIR; 27 | std::string savestatesDirectory = CONFIG_SAVESTATES_DIR; 28 | std::string tempDirectory = CONFIG_TEMP_DIR; 29 | 30 | std::string getExecutableDirectory() { 31 | return executableDirectory; 32 | } 33 | 34 | std::string getOutputDirectory() { 35 | return outputDirectory; 36 | } 37 | 38 | std::string getBakefilesDirectory() { 39 | return bakefilesDirectory; 40 | } 41 | 42 | std::string getLogsDirectory() { 43 | return logsDirectory; 44 | } 45 | 46 | std::string getSavestatesDirectory() { 47 | return savestatesDirectory; 48 | } 49 | 50 | std::string getTempDirectory() { 51 | return tempDirectory; 52 | } 53 | 54 | void setOutputDirectory(std::string dir) { 55 | outputDirectory = dir; 56 | } 57 | 58 | void setBakefilesDirectory(std::string dir) { 59 | bakefilesDirectory = dir; 60 | } 61 | 62 | void setLogsDirectory(std::string dir) { 63 | logsDirectory = dir; 64 | } 65 | 66 | void setSavestatesDirectory(std::string dir) { 67 | savestatesDirectory = dir; 68 | } 69 | 70 | void setTempDirectory(std::string dir) { 71 | tempDirectory = dir; 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /src/config.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef FLUIDSIM_CONFIG_H 21 | #define FLUIDSIM_CONFIG_H 22 | 23 | #define CONFIG_EXECUTABLE_DIR "@CONFIG_EXECUTABLE_DIR@" 24 | #define CONFIG_OUTPUT_DIR "@CONFIG_OUTPUT_DIR@" 25 | #define CONFIG_BAKEFILES_DIR "@CONFIG_BAKEFILES_DIR@" 26 | #define CONFIG_LOGS_DIR "@CONFIG_LOGS_DIR@" 27 | #define CONFIG_SAVESTATES_DIR "@CONFIG_SAVESTATES_DIR@" 28 | #define CONFIG_TEMP_DIR "@CONFIG_TEMP_DIR@" 29 | 30 | #include 31 | 32 | namespace Config { 33 | 34 | extern std::string executableDirectory; 35 | extern std::string outputDirectory; 36 | extern std::string bakefilesDirectory; 37 | extern std::string logsDirectory; 38 | extern std::string savestatesDirectory; 39 | extern std::string tempDirectory; 40 | 41 | extern std::string getExecutableDirectory(); 42 | extern std::string getOutputDirectory(); 43 | extern std::string getBakefilesDirectory(); 44 | extern std::string getLogsDirectory(); 45 | extern std::string getSavestatesDirectory(); 46 | extern std::string getTempDirectory(); 47 | 48 | extern void setOutputDirectory(std::string dir); 49 | extern void setBakefilesDirectory(std::string dir); 50 | extern void setLogsDirectory(std::string dir); 51 | extern void setSavestatesDirectory(std::string dir); 52 | extern void setTempDirectory(std::string dir); 53 | 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/cuboidfluidsource.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "cuboidfluidsource.h" 21 | 22 | CuboidFluidSource::CuboidFluidSource() { 23 | } 24 | 25 | CuboidFluidSource::CuboidFluidSource(vmath::vec3 position, 26 | double w, double h, double d) : 27 | FluidSource(), 28 | _bbox(position, w, h, d) { 29 | } 30 | 31 | CuboidFluidSource::CuboidFluidSource(AABB bbox) : 32 | FluidSource(), 33 | _bbox(bbox) { 34 | } 35 | 36 | CuboidFluidSource::CuboidFluidSource(vmath::vec3 position, 37 | double w, double h, double d, 38 | vmath::vec3 velocity) : 39 | FluidSource(velocity), 40 | _bbox(position, w, h, d) { 41 | } 42 | 43 | CuboidFluidSource::CuboidFluidSource(AABB bbox, vmath::vec3 velocity) : 44 | FluidSource(velocity), 45 | _bbox(bbox) { 46 | } 47 | 48 | CuboidFluidSource::~CuboidFluidSource() { 49 | } 50 | 51 | vmath::vec3 CuboidFluidSource::getPosition() { 52 | return _bbox.position; 53 | } 54 | 55 | void CuboidFluidSource::setPosition(vmath::vec3 p) { 56 | _bbox.position = p; 57 | } 58 | 59 | AABB CuboidFluidSource::getAABB() { 60 | return _bbox; 61 | } 62 | 63 | void CuboidFluidSource::setAABB(AABB bbox) { 64 | _bbox = bbox; 65 | } 66 | 67 | bool CuboidFluidSource::containsPoint(vmath::vec3 p) { 68 | return _bbox.isPointInside(p); 69 | } 70 | 71 | void CuboidFluidSource::setWidth(double w) { 72 | _bbox.width = w; 73 | } 74 | 75 | void CuboidFluidSource::setHeight(double h) { 76 | _bbox.height = h; 77 | } 78 | 79 | void CuboidFluidSource::setDepth(double d) { 80 | _bbox.depth = d; 81 | } 82 | 83 | double CuboidFluidSource::getWidth() { 84 | return _bbox.width; 85 | } 86 | 87 | double CuboidFluidSource::getHeight() { 88 | return _bbox.height; 89 | } 90 | 91 | double CuboidFluidSource::getDepth() { 92 | return _bbox.depth; 93 | } 94 | 95 | vmath::vec3 CuboidFluidSource::getCenter() { 96 | return vmath::vec3(_bbox.position.x + 0.5*_bbox.width, 97 | _bbox.position.y + 0.5*_bbox.height, 98 | _bbox.position.z + 0.5*_bbox.depth); 99 | } 100 | 101 | void CuboidFluidSource::setCenter(vmath::vec3 pos) { 102 | vmath::vec3 c = getCenter(); 103 | vmath::vec3 trans = pos - c; 104 | _bbox.position += trans; 105 | } 106 | 107 | void CuboidFluidSource::expand(double value) { 108 | _bbox.expand(value); 109 | } 110 | 111 | void CuboidFluidSource::_getOverlappingCells(GridIndexVector &indices, double dx) { 112 | int isize = indices.width; 113 | int jsize = indices.height; 114 | int ksize = indices.depth; 115 | GridIndex gmin, gmax; 116 | Grid3d::getGridIndexBounds(_bbox, dx, isize, jsize, ksize, &gmin, &gmax); 117 | 118 | for (int k = gmin.k; k <= gmax.k; k++) { 119 | for (int j = gmin.j; j <= gmax.j; j++) { 120 | for (int i = gmin.i; i <= gmax.i; i++) { 121 | indices.push_back(i, j, k); 122 | } 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/cuboidfluidsource.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef CUBOIDFLUIDSOURCE_H 21 | #define CUBOIDFLUIDSOURCE_H 22 | 23 | #include "fluidsource.h" 24 | 25 | #include 26 | 27 | #include "vmath.h" 28 | #include "aabb.h" 29 | #include "fluidmaterialgrid.h" 30 | 31 | class CuboidFluidSource : public FluidSource 32 | { 33 | public: 34 | CuboidFluidSource(); 35 | CuboidFluidSource(vmath::vec3 position, double w, double h, double d); 36 | CuboidFluidSource(AABB bbox); 37 | CuboidFluidSource(vmath::vec3 position, double w, double h, double d, 38 | vmath::vec3 velocity); 39 | CuboidFluidSource(AABB bbox, vmath::vec3 velocity); 40 | ~CuboidFluidSource(); 41 | 42 | virtual vmath::vec3 getPosition(); 43 | virtual void setPosition(vmath::vec3 pos); 44 | virtual AABB getAABB(); 45 | virtual bool containsPoint(vmath::vec3 p); 46 | 47 | void setWidth(double w); 48 | void setHeight(double h); 49 | void setDepth(double d); 50 | double getWidth(); 51 | double getHeight(); 52 | double getDepth(); 53 | void setAABB(AABB bbox); 54 | vmath::vec3 getCenter(); 55 | void setCenter(vmath::vec3 pos); 56 | void expand(double value); 57 | 58 | private: 59 | AABB _bbox; 60 | 61 | virtual void _getOverlappingCells(GridIndexVector &storage, double dx); 62 | }; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/diffuseparticle.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef DIFFUSEPARTICLE_H 21 | #define DIFFUSEPARTICLE_H 22 | 23 | #include "vmath.h" 24 | 25 | enum class DiffuseParticleType : char { 26 | bubble = 0x00, 27 | foam = 0x01, 28 | spray = 0x02, 29 | notset = 0x03 30 | }; 31 | 32 | struct DiffuseParticle { 33 | vmath::vec3 position; 34 | vmath::vec3 velocity; 35 | float lifetime; 36 | DiffuseParticleType type; 37 | 38 | DiffuseParticle() : lifetime(0.0), 39 | type(DiffuseParticleType::notset) {} 40 | 41 | DiffuseParticle(vmath::vec3 p, vmath::vec3 v, float time) : 42 | position(p), 43 | velocity(v), 44 | lifetime(time), 45 | type(DiffuseParticleType::notset) {} 46 | }; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /src/examples/cpp/example_dambreak.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "../../fluidsimulation.h" 21 | #include "../../vmath.h" 22 | 23 | void example_dambreak() { 24 | 25 | // This example will run a dambreak scenario where 26 | // a cuboid of fluid is released at one side of the 27 | // simulation domain. 28 | 29 | int isize = 128; 30 | int jsize = 64; 31 | int ksize = 64; 32 | double dx = 0.125; 33 | FluidSimulation fluidsim(isize, jsize, ksize, dx); 34 | 35 | double width, height, depth; 36 | fluidsim.getSimulationDimensions(&width, &height, &depth); 37 | 38 | AABB bbox; 39 | bbox.position = vmath::vec3(0, 0, 0); 40 | bbox.width = 0.25*width; 41 | bbox.height = 0.75*height; 42 | bbox.depth = depth; 43 | 44 | fluidsim.addFluidCuboid(bbox); 45 | 46 | fluidsim.addBodyForce(0.0, -25.0, 0.0); 47 | fluidsim.initialize(); 48 | 49 | double timestep = 1.0 / 30.0; 50 | for (;;) { 51 | fluidsim.update(timestep); 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /src/examples/cpp/example_diffuse_inflow.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "../../fluidsimulation.h" 21 | 22 | void example_diffuse_inflow() { 23 | 24 | // This example will initialize an inflow fluid source and a 25 | // solid pillar obstacle. Foam/bubble/spray particles will be 26 | // generated by enabling the diffuse particle simulation feature 27 | // 28 | // Diffuse particles are output as a vertex only .PLY meshes 29 | // with the "diffuse" prefix followed by the frame number. 30 | // 31 | // ex: diffuse000000.ply, diffuse000001.ply, diffuse000002.ply 32 | 33 | int isize = 256; 34 | int jsize = 128; 35 | int ksize = 128; 36 | double dx = 0.0625; 37 | FluidSimulation fluidsim(isize, jsize, ksize, dx); 38 | 39 | // This option enables the diffuse particle simulation 40 | fluidsim.enableDiffuseMaterialOutput(); 41 | 42 | // Maximum lifetime of a diffuse particle in seconds. 43 | // This value controls how quickly/slowly diffuse particles 44 | // fade from the simulation. 45 | fluidsim.setMaxDiffuseParticleLifetime(3.0); 46 | 47 | // Diffuse particles are generated in areas where the fluid 48 | // is likely to be aerated such as at wavecrests and areas of high 49 | // turbulence. This function call sets the wavecrest emission rate 50 | // and turbulence emission rate to the same values. 51 | // 52 | // To set different separate rates, use 53 | // setDiffuseParticleWavecrestEmissionRate(double) 54 | // setDiffuseParticleTurbulenceEmissionRate(double) 55 | fluidsim.setDiffuseParticleEmissionRates(37.0); 56 | 57 | // Limit the maximum number of particles simulated by the diffuse 58 | // particle simulator. 59 | fluidsim.setMaxNumDiffuseParticles(6e6); 60 | 61 | double width, height, depth; 62 | fluidsim.getSimulationDimensions(&width, &height, &depth); 63 | 64 | // Initialize inflow fluid source located at one end of the 65 | // of the simulation domain. 66 | AABB inflowAABB(vmath::vec3(), 5*dx, 25*dx, 40*dx); 67 | vmath::vec3 inflowVelocity = vmath::vec3(10.0, 0.0, 0.0); 68 | CuboidFluidSource inflow(inflowAABB, inflowVelocity); 69 | inflow.setCenter(vmath::vec3(5*dx, 0.5*height, 0.5*depth)); 70 | fluidsim.addCuboidFluidSource(&inflow); 71 | 72 | // Create a pillar of solid cells in the center of the domain 73 | std::vector solidCells; 74 | vmath::vec3 center(0.5*width, 0.5*height, 0.5*depth); 75 | double pillarRadius = 15*dx; 76 | double rsq = pillarRadius * pillarRadius; 77 | for (int k = 0; k < ksize; k++) { 78 | for (int j = 0; j < jsize; j++) { 79 | for (int i = 0; i < isize; i++) { 80 | vmath::vec3 gpos = Grid3d::GridIndexToCellCenter(i, j, k, dx); 81 | vmath::vec3 v = gpos - center; 82 | double distsq = v.x*v.x + v.z*v.z; 83 | 84 | if (distsq < rsq) { 85 | solidCells.push_back(GridIndex(i, j, k)); 86 | } 87 | } 88 | } 89 | } 90 | fluidsim.addSolidCells(solidCells); 91 | 92 | fluidsim.addBodyForce(0.0, -25.0, 0.0); 93 | fluidsim.initialize(); 94 | 95 | double timestep = 1.0 / 30.0; 96 | for (;;) { 97 | fluidsim.update(timestep); 98 | } 99 | 100 | } -------------------------------------------------------------------------------- /src/examples/cpp/example_gravity_field.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include 21 | 22 | #include "../../fluidsimulation.h" 23 | #include "../../grid3d.h" 24 | #include "../../vmath.h" 25 | 26 | std::vector getCellsWithinRadius(vmath::vec3 position, double radius, FluidSimulation *fluidsim) { 27 | 28 | int isize, ksize, jsize; 29 | fluidsim->getGridDimensions(&isize, &jsize, &ksize); 30 | double dx = fluidsim->getCellSize(); 31 | 32 | std::vector cells; 33 | double rsq = radius*radius; 34 | for (int k = 0; k < ksize; k++) { 35 | for (int j = 0; j < jsize; j++) { 36 | for (int i = 0; i < isize; i++) { 37 | vmath::vec3 v = Grid3d::GridIndexToCellCenter(i, j, k, dx) - position; 38 | if (v.lengthsq() < rsq) { 39 | cells.push_back(GridIndex(i, j, k)); 40 | } 41 | } 42 | } 43 | } 44 | 45 | return cells; 46 | } 47 | 48 | vmath::vec3 rotateY(vmath::vec3 v, float rads) { 49 | float x = v.z*sin(rads) + v.x*cos(rads); 50 | float y = v.y; 51 | float z = v.z*cos(rads) - v.x*sin(rads); 52 | 53 | return vmath::vec3(x, y, z); 54 | } 55 | 56 | int ISIZE = 256; 57 | int JSIZE = 256; 58 | int KSIZE = 256; 59 | double DX = 0.0625; 60 | vmath::vec3 gravityForceField(vmath::vec3 p) { 61 | vmath::vec3 center(0.5*(double)ISIZE*DX, 62 | 0.5*(double)JSIZE*DX, 63 | 0.5*(double)KSIZE*DX); 64 | 65 | double ming = 1.0; 66 | double maxg = 25.0; 67 | double mindsq = 1.0; 68 | double maxdsq = 8.0*8.0; 69 | 70 | vmath::vec3 v = center - p; 71 | double distsq = v.lengthsq(); 72 | 73 | double eps = 1e-6; 74 | if (distsq < eps) { 75 | return vmath::vec3(); 76 | } 77 | 78 | double distfactor = 1.0 - (distsq - mindsq) / (maxdsq - mindsq); 79 | double gstrength = ming + distfactor*(maxg - ming); 80 | 81 | return (float)gstrength*v.normalize(); 82 | } 83 | 84 | void example_gravity_field() { 85 | 86 | // This example will recreate this fluid simulation: 87 | // https://gfycat.com/SphericalHandsomeIndochinesetiger 88 | // 89 | // Fluid is emitted from a spherical fluid source that oscillates 90 | // its emission direction. 91 | // 92 | // The fluid in the simulation domain will be under the influence 93 | // of a variable gravity force field. The force field generates a gravity 94 | // vector towards a sphere in the center of the fluid domain with force 95 | // strength falling off proportional to radius^2. 96 | 97 | int isize = ISIZE; 98 | int jsize = JSIZE; 99 | int ksize = KSIZE; 100 | double dx = DX; 101 | FluidSimulation fluidsim(isize, jsize, ksize, dx); 102 | 103 | fluidsim.setSurfaceSubdivisionLevel(2); 104 | fluidsim.setNumPolygonizerSlices(4); 105 | 106 | double width, height, depth; 107 | fluidsim.getSimulationDimensions(&width, &height, &depth); 108 | 109 | vmath::vec3 center(0.5*width, 0.5*height, 0.5*depth); 110 | double radius = 2.0; 111 | std::vector solidCells = getCellsWithinRadius(center, radius, &fluidsim); 112 | fluidsim.addSolidCells(solidCells); 113 | 114 | vmath::vec3 emitterPosition(0.5*width, 0.9*height, 0.5*depth); 115 | vmath::vec3 emitterVelocity(8.0, 0.0, 0.0); 116 | double emitterRadius = 1.0; 117 | SphericalFluidSource emitter(emitterPosition, emitterRadius, emitterVelocity); 118 | fluidsim.addSphericalFluidSource(&emitter); 119 | 120 | fluidsim.addBodyForce(gravityForceField); 121 | 122 | fluidsim.initialize(); 123 | 124 | double timestep = 1.0/60.0; 125 | double simulationTime = 0.0; 126 | for (;;) { 127 | 128 | int frameno = fluidsim.getCurrentFrame(); 129 | if (frameno >= 200) { 130 | emitter.deactivate(); 131 | } 132 | 133 | double pi = 3.14159265; 134 | double minAngle = -0.25*pi; 135 | double maxAngle = 0.25*pi; 136 | double rotationSpeed = 0.75*pi; 137 | double rotationFactor = sin(rotationSpeed*simulationTime); 138 | double rads = minAngle + rotationFactor*(maxAngle - minAngle); 139 | vmath::vec3 rotatedVelocity = rotateY(emitterVelocity, rads); 140 | emitter.setVelocity(rotatedVelocity); 141 | 142 | fluidsim.update(timestep); 143 | 144 | simulationTime += timestep; 145 | } 146 | 147 | } -------------------------------------------------------------------------------- /src/examples/cpp/example_import_mesh_obstacle.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "../../fluidsimulation.h" 21 | #include "../../trianglemesh.h" 22 | #include "../../array3d.h" 23 | #include "../../utils.h" 24 | #include "../../vmath.h" 25 | 26 | #include 27 | 28 | bool file_exists(std::string filename) { 29 | std::ifstream infile(filename); 30 | return infile.good(); 31 | } 32 | 33 | bool add_mesh_obstacle(std::string meshpath, FluidSimulation *fluidsim) { 34 | 35 | if (!file_exists(meshpath)) { 36 | std::cout << "ERROR: Could not open file [" << meshpath << "]" << std::endl; 37 | return false; 38 | } 39 | 40 | TriangleMesh mesh; 41 | bool success = mesh.loadPLY(meshpath); 42 | if (!success) { 43 | std::cout << "ERROR: Could not load PLY file [" << meshpath << "]" << std::endl; 44 | return false; 45 | } 46 | 47 | std::cout << "Loaded PLY mesh with " << mesh.vertices.size() << " vertices " << 48 | "and " << mesh.triangles.size() << " triangles." << std::endl; 49 | 50 | // uncomment to translate mesh 51 | //mesh.translate(vmath::vec3(4.0, 0.0, 0.0)); 52 | 53 | int isize, jsize, ksize; 54 | fluidsim->getGridDimensions(&isize, &jsize, &ksize); 55 | double dx = fluidsim->getCellSize(); 56 | 57 | std::vector cells; 58 | utils::getCellsInsideTriangleMesh(mesh, dx, cells); 59 | 60 | // Filter out cells that lie outside of the simulation domain 61 | std::vector cellsInsideDomain; 62 | for (size_t i = 0; i < cells.size(); i++) { 63 | GridIndex g = cells[i]; 64 | if (g.i >= 0 && g.j >= 0 && g.k >= 0 && g.i < isize && g.j < jsize && g.k < ksize) { 65 | cellsInsideDomain.push_back(g); 66 | } 67 | } 68 | 69 | std::cout << "Converted mesh into " << cellsInsideDomain.size() << " grid cells." << std::endl; 70 | 71 | fluidsim->addSolidCells(cellsInsideDomain); 72 | 73 | return true; 74 | } 75 | 76 | void example_import_mesh_obstacle() { 77 | 78 | /* 79 | This example will demonstrate how to convert a triangle mesh to a set 80 | of grid cells that can be added to the fluid domain as a solid object. 81 | 82 | Notes: - the triangle mesh must be watertight (no holes) to be accurately 83 | converted into solid cells 84 | 85 | - all faces in the triangle mesh must be triangles 86 | 87 | - the triangle mesh must be in the stanford .PLY file format 88 | (http://paulbourke.net/dataformats/ply/) 89 | 90 | - the .PLY mesh header must be in the following format: 91 | 92 | ply 93 | format binary_little_endian 1.0 94 | element vertex REPLACE_WITH_NUM_VERTICES 95 | property float x 96 | property float y 97 | property float z 98 | element face REPLACE_WITH_NUM_FACES 99 | property list uchar int vertex_index 100 | end_header 101 | */ 102 | 103 | int isize = 64; 104 | int jsize = 64; 105 | int ksize = 64; 106 | double dx = 0.125; 107 | FluidSimulation fluidsim(isize, jsize, ksize, dx); 108 | 109 | double width, height, depth; 110 | fluidsim.getSimulationDimensions(&width, &height, &depth); 111 | fluidsim.addImplicitFluidPoint(width/2, height/2, depth/2, 7.0); 112 | 113 | fluidsim.addBodyForce(0.0, 0.0, -25.0); 114 | fluidsim.initialize(); 115 | 116 | std::string meshpath = "PATH_TO_PLY_FILE.ply"; 117 | bool success = add_mesh_obstacle(meshpath, &fluidsim); 118 | if (!success) { 119 | return; 120 | } 121 | 122 | double timestep = 1.0 / 30.0; 123 | for (;;) { 124 | fluidsim.update(timestep); 125 | } 126 | 127 | } -------------------------------------------------------------------------------- /src/examples/cpp/example_inflow_outflow.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include 21 | 22 | #include "../../fluidsimulation.h" 23 | #include "../../grid3d.h" 24 | #include "../../vmath.h" 25 | 26 | void example_inflow_outflow() { 27 | 28 | // This example will add an inflow fluid source whose 29 | // position oscillates between two points. 30 | // 31 | // An outflow fluid source will be placed at one end of 32 | // the simulation domain to drain fluid. 33 | // 34 | // A solid pillar will be placed in the center of the 35 | // simulation domain. 36 | 37 | int isize = 128; 38 | int jsize = 64; 39 | int ksize = 64; 40 | double dx = 0.125; 41 | FluidSimulation fluidsim(isize, jsize, ksize, dx); 42 | 43 | double width, height, depth; 44 | fluidsim.getSimulationDimensions(&width, &height, &depth); 45 | 46 | // Initialize fluid sources 47 | AABB inflowAABB; 48 | inflowAABB.position = vmath::vec3(0.0, 0.0, 0.0); 49 | inflowAABB.width = 5*dx; 50 | inflowAABB.height = 15*dx; 51 | inflowAABB.depth = 30*dx; 52 | vmath::vec3 inflowVelocity = vmath::vec3(10.0, 0.0, 0.0); 53 | CuboidFluidSource inflow(inflowAABB, inflowVelocity); 54 | 55 | AABB outflowAABB; 56 | outflowAABB.position = vmath::vec3(width - 5*dx, 0.0, 0.0); 57 | outflowAABB.width = 10*dx; 58 | outflowAABB.height = height; 59 | outflowAABB.depth = depth; 60 | CuboidFluidSource outflow(outflowAABB); 61 | outflow.setAsOutflow(); 62 | 63 | fluidsim.addCuboidFluidSource(&inflow); 64 | fluidsim.addCuboidFluidSource(&outflow); 65 | 66 | // Create a pillar of solid cells in the center of the domain 67 | std::vector solidCells; 68 | vmath::vec3 center(0.5*width, 0.5*height, 0.5*depth); 69 | double pillarRadius = 10*dx; 70 | double rsq = pillarRadius * pillarRadius; 71 | for (int k = 0; k < ksize; k++) { 72 | for (int j = 0; j < jsize; j++) { 73 | for (int i = 0; i < isize; i++) { 74 | vmath::vec3 gpos = Grid3d::GridIndexToCellCenter(i, j, k, dx); 75 | vmath::vec3 v = gpos - center; 76 | double distsq = v.x*v.x + v.z*v.z; 77 | 78 | if (distsq < rsq) { 79 | solidCells.push_back(GridIndex(i, j, k)); 80 | } 81 | } 82 | } 83 | } 84 | fluidsim.addSolidCells(solidCells); 85 | 86 | fluidsim.addBodyForce(0.0, -25.0, 0.0); 87 | fluidsim.initialize(); 88 | 89 | double timestep = 1.0 / 30.0; 90 | double runtime = 0.0; 91 | for (;;) { 92 | runtime += timestep; 93 | 94 | // Oscillate position of inflow source between two points 95 | double ocspeed = 0.5*3.14159; 96 | double sinval = 0.5 + 0.5*sin(runtime*ocspeed); 97 | 98 | vmath::vec3 p1(0.1*width, 0.15*height, 0.5*depth); 99 | vmath::vec3 p2(0.1*width, 0.85*height, 0.5*depth); 100 | vmath::vec3 p12 = p2 - p1; 101 | vmath::vec3 sourcepos = p1 + sinval*p12; 102 | inflow.setCenter(sourcepos); 103 | 104 | fluidsim.update(timestep); 105 | } 106 | 107 | } -------------------------------------------------------------------------------- /src/examples/cpp/example_lego_sphere_drop.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "../../fluidsimulation.h" 21 | 22 | void example_lego_sphere_drop() { 23 | 24 | // This example will drop a ball of fluid to a pool 25 | // of resting fluid. The output surface mesh will be generated 26 | // as LEGO bricks. 27 | // 28 | // The brick surface reconstruction method requires data from 29 | // three consecutive frames, so data output will not be written 30 | // to disk until the third frame. 31 | 32 | int isize = 128; 33 | int jsize = 128; 34 | int ksize = 128; 35 | double dx = 0.0625; 36 | FluidSimulation fluidsim(isize, jsize, ksize, dx); 37 | 38 | fluidsim.disableIsotropicSurfaceReconstruction(); 39 | 40 | double brickWidth = 3*dx; 41 | double brickHeight = 1.2*brickWidth; 42 | double brickDepth = brickWidth; 43 | fluidsim.enableBrickOutput(brickWidth, brickHeight, brickDepth); 44 | 45 | double width, height, depth; 46 | fluidsim.getSimulationDimensions(&width, &height, &depth); 47 | fluidsim.addImplicitFluidPoint(width/2, height/2, depth/2, 5.0); 48 | 49 | fluidsim.addFluidCuboid(0.0, 0.0, 0.0, width, 0.125*height, depth); 50 | 51 | fluidsim.addBodyForce(0.0, -25.0, 0.0); 52 | fluidsim.initialize(); 53 | 54 | double timestep = 1.0 / 30.0; 55 | for (;;) { 56 | fluidsim.update(timestep); 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /src/examples/cpp/example_save_load_state.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include 21 | 22 | #include "../../fluidsimulation.h" 23 | #include "../../fluidsimulationsavestate.h" 24 | #include "../../config.h" 25 | #include "../../fluidsimassert.h" 26 | 27 | void example_save_state(std::string filename) { 28 | 29 | int isize = 64; 30 | int jsize = 64; 31 | int ksize = 64; 32 | double dx = 0.125; 33 | FluidSimulation fluidsim(isize, jsize, ksize, dx); 34 | 35 | fluidsim.disableAutosave(); 36 | 37 | double width, height, depth; 38 | fluidsim.getSimulationDimensions(&width, &height, &depth); 39 | fluidsim.addImplicitFluidPoint(width/2, 0.0, depth/2, 7.0); 40 | 41 | fluidsim.addBodyForce(0.0, -25.0, 0.0); 42 | fluidsim.initialize(); 43 | 44 | double timestep = 1.0 / 30.0; 45 | int numFrames = 5; 46 | while (fluidsim.getCurrentFrame() < numFrames) { 47 | fluidsim.update(timestep); 48 | } 49 | 50 | fluidsim.saveState(filename); 51 | } 52 | 53 | void example_load_state(std::string filename) { 54 | 55 | FluidSimulationSaveState state; 56 | bool success = state.loadState(filename); 57 | FLUIDSIM_ASSERT(success); 58 | 59 | FluidSimulation fluidsim(state); 60 | 61 | /* 62 | After constructing the FluidSimulation object, the save state is 63 | no longer needed and can be closed. Closing the state will 64 | clean up any temporary files that were created during loading 65 | the state and initializing the fluid simulation. 66 | */ 67 | state.closeState(); 68 | 69 | /* 70 | The save state feature only saves the following data: 71 | - grid dimensions and cell size 72 | - current frame 73 | - marker particles 74 | - diffuse particles 75 | - solid cells 76 | - FluidBrickGrid data 77 | 78 | The save state will not load any changed settings, body forces, 79 | or fluid sources, so these attributes/objects will need to be re-added 80 | manually if desired once the state is loaded. 81 | 82 | The initialize() method does not need to be called when loading a simulation 83 | from a save state. The simulation is initialized within the constructor. 84 | */ 85 | 86 | fluidsim.disableAutosave(); 87 | fluidsim.addBodyForce(0.0, -25.0, 0.0); 88 | 89 | double timestep = 1.0 / 30.0; 90 | int numFrames = 5; 91 | int maxFrameNo = fluidsim.getCurrentFrame() + numFrames; 92 | while (fluidsim.getCurrentFrame() < maxFrameNo) { 93 | fluidsim.update(timestep); 94 | } 95 | } 96 | 97 | void example_save_load_state() { 98 | 99 | // The fluid simulator generates an autosave state 100 | // at the start of each frame by default. 101 | // 102 | // This example will turn off the autosave feature and demonstrate 103 | // how to manually save and load a savestate. 104 | 105 | std::string dir = Config::getSavestatesDirectory(); 106 | std::string filename = dir + "/mySaveState.state"; 107 | example_save_state(filename); 108 | example_load_state(filename); 109 | } 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /src/examples/cpp/example_sphere_drop.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "../../fluidsimulation.h" 21 | 22 | void example_sphere_drop() { 23 | 24 | // This example will drop a ball of fluid in the center 25 | // of a rectangular fluid simulation domain. 26 | 27 | int isize = 256; 28 | int jsize = 128; 29 | int ksize = 128; 30 | double dx = 0.0625; 31 | FluidSimulation fluidsim(isize, jsize, ksize, dx); 32 | 33 | // Increase subdivision level to increase the resolution that 34 | // the output meshes are generated at. 35 | int subdivisionLevel = 1; 36 | fluidsim.setSurfaceSubdivisionLevel(subdivisionLevel); 37 | 38 | if (subdivisionLevel >= 2) { 39 | // Helps reduce output filesize by removing polyhedrons 40 | // that do not meet a minimum triangle count threshold. 41 | fluidsim.setMinPolyhedronTriangleCount(64); 42 | } 43 | 44 | double width, height, depth; 45 | fluidsim.getSimulationDimensions(&width, &height, &depth); 46 | fluidsim.addImplicitFluidPoint(width/2, height/2, depth/2, 7.0); 47 | 48 | fluidsim.addBodyForce(0.0, -25.0, 0.0); 49 | fluidsim.initialize(); 50 | 51 | double timestep = 1.0 / 30.0; 52 | for (;;) { 53 | fluidsim.update(timestep); 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /src/examples/python/example_dambreak.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Ryan L. Guy 2 | # 3 | # This software is provided 'as-is', without any express or implied 4 | # warranty. In no event will the authors be held liable for any damages 5 | # arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, 8 | # including commercial applications, and to alter it and redistribute it 9 | # freely, subject to the following restrictions: 10 | # 11 | # 1. The origin of this software must not be misrepresented; you must not 12 | # claim that you wrote the original software. If you use this software 13 | # in a product, an acknowledgement in the product documentation would be 14 | # appreciated but is not required. 15 | # 2. Altered source versions must be plainly marked as such, and must not be 16 | # misrepresented as being the original software. 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | 19 | import sys, os 20 | 21 | if len(sys.argv) >= 2: 22 | sys.path.append(os.path.abspath(sys.argv[1])) 23 | else: 24 | filepath = os.path.dirname(__file__) 25 | guesspath = os.path.abspath(os.path.join(filepath, os.pardir)) 26 | guesspath = os.path.abspath(os.path.join(guesspath, os.pardir)) 27 | sys.path.append(guesspath) 28 | 29 | try: 30 | import pyfluid 31 | except ImportError: 32 | errmsg = ("Could not find the pyfluid package. Pass the directory that contains the " + 33 | "pyfluid package as a command line argument and try again. " + 34 | "For example, if the package is located at 'build/fluidsim/pyfluid', " + 35 | "then pass the directory 'build/fluidsim/'\n\n" + 36 | "Usage:\tpython example_dambreak.py path/to/directory\n") 37 | raise ImportError(errmsg) 38 | 39 | # This example will run a dambreak scenario where a cuboid of fluid is released 40 | # at one side of the simulation domain. 41 | from pyfluid import FluidSimulation, AABB, Vector3 42 | 43 | isize = 128 44 | jsize = 64 45 | ksize = 64 46 | dx = 0.125 47 | fluidsim = FluidSimulation(isize, jsize, ksize, dx) 48 | 49 | width, height, depth = fluidsim.get_simulation_dimensions() 50 | cuboid = AABB(Vector3(0, 0, 0), 0.25*width, 0.75*height, depth) 51 | fluidsim.add_fluid_cuboid(cuboid) 52 | 53 | fluidsim.add_body_force(0.0, -25.0, 0.0) 54 | fluidsim.initialize() 55 | 56 | timestep = 1.0/30.0 57 | while True: 58 | fluidsim.update(timestep) 59 | -------------------------------------------------------------------------------- /src/examples/python/example_diffuse_inflow.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Ryan L. Guy 2 | # 3 | # This software is provided 'as-is', without any express or implied 4 | # warranty. In no event will the authors be held liable for any damages 5 | # arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, 8 | # including commercial applications, and to alter it and redistribute it 9 | # freely, subject to the following restrictions: 10 | # 11 | # 1. The origin of this software must not be misrepresented; you must not 12 | # claim that you wrote the original software. If you use this software 13 | # in a product, an acknowledgement in the product documentation would be 14 | # appreciated but is not required. 15 | # 2. Altered source versions must be plainly marked as such, and must not be 16 | # misrepresented as being the original software. 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | 19 | import sys, os 20 | 21 | if len(sys.argv) >= 2: 22 | sys.path.append(os.path.abspath(sys.argv[1])) 23 | else: 24 | filepath = os.path.dirname(__file__) 25 | guesspath = os.path.abspath(os.path.join(filepath, os.pardir)) 26 | guesspath = os.path.abspath(os.path.join(guesspath, os.pardir)) 27 | sys.path.append(guesspath) 28 | 29 | try: 30 | import pyfluid 31 | except ImportError: 32 | errmsg = ("Could not find the pyfluid package. Pass the directory that contains the " + 33 | "pyfluid package as a command line argument and try again. " + 34 | "For example, if the package is located at 'build/fluidsim/pyfluid', " + 35 | "then pass the directory 'build/fluidsim/'\n\n" + 36 | "Usage:\tpython example_diffuse_inflow.py path/to/directory\n") 37 | raise ImportError(errmsg) 38 | 39 | # This example will initialize an inflow fluid source and a 40 | # solid pillar obstacle. Foam/bubble/spray particles will be 41 | # generated by enabling the diffuse particle simulation feature 42 | # 43 | # Diffuse particles are output as a vertex only .PLY meshes 44 | # with the "diffuse" prefix followed by the frame number. 45 | # 46 | # ex: diffuse000000.ply, diffuse000001.ply, diffuse000002.ply 47 | import math 48 | from pyfluid import FluidSimulation, CuboidFluidSource, AABB, Vector3, GridIndex 49 | 50 | def get_pillar_cells(position, radius, isize, jsize, ksize, dx): 51 | rsq = radius*radius 52 | cells = [] 53 | for k in range(ksize): 54 | for j in range(jsize): 55 | for i in range(isize): 56 | vx = (i + 0.5)*dx - position.x 57 | vz = (k + 0.5)*dx - position.z 58 | distsq = vx*vx + vz*vz 59 | if distsq < rsq: 60 | cells.append(GridIndex(i, j, k)) 61 | 62 | return cells 63 | 64 | 65 | isize = 256 66 | jsize = 128 67 | ksize = 128 68 | dx = 0.0625 69 | fluidsim = FluidSimulation(isize, jsize, ksize, dx) 70 | 71 | # This option enables the diffuse particle simulation 72 | fluidsim.enable_diffuse_material_output = True 73 | 74 | # Maximum lifetime of a diffuse particle in seconds. This value controls how 75 | # quickly/slowly diffuse particles fade from the simulation. 76 | fluidsim.max_diffuse_particle_lifetime = 3.0 77 | 78 | # Diffuse particles are generated in areas where the fluid 79 | # is likely to be aerated such as at wavecrests and areas of high 80 | # turbulence. These properties set the wavecrest emission rate 81 | # and turbulence emission rates. 82 | fluidsim.diffuse_particle_wavecrest_emission_rate = 37.0 83 | fluidsim.diffuse_particle_turbulence_emission_rate = 37.0 84 | 85 | # Limit the maximum number of particles simulated by the diffuse particle 86 | # simulator. 87 | fluidsim.max_num_diffuse_particles = int(6e6) 88 | 89 | width, height, depth = fluidsim.get_simulation_dimensions() 90 | 91 | # Initialize inflow fluid source located at one end of the 92 | # of the simulation domain. 93 | inflow_bbox = AABB(Vector3(), 5*dx, 25*dx, 40*dx) 94 | inflow_velocity = Vector3(10.0, 0.0, 0.0) 95 | fluid_inflow = CuboidFluidSource(inflow_bbox, inflow_velocity) 96 | fluid_inflow.center = Vector3(5*dx, 0.5*height, 0.5*depth) 97 | fluid_inflow.is_inflow = True 98 | fluidsim.add_cuboid_fluid_source(fluid_inflow) 99 | 100 | # Create a pillar of solid cells in the center of the domain 101 | center = Vector3(0.5*width, 0.5*height, 0.5*depth) 102 | radius = 15*dx 103 | pillar_cells = get_pillar_cells(center, radius, isize, jsize, ksize, dx) 104 | fluidsim.add_solid_cells(pillar_cells) 105 | 106 | fluidsim.add_body_force(0.0, -25.0, 0.0) 107 | fluidsim.initialize() 108 | 109 | timestep = 1.0/30.0 110 | while True: 111 | fluidsim.update(timestep) 112 | -------------------------------------------------------------------------------- /src/examples/python/example_inflow_outflow.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Ryan L. Guy 2 | # 3 | # This software is provided 'as-is', without any express or implied 4 | # warranty. In no event will the authors be held liable for any damages 5 | # arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, 8 | # including commercial applications, and to alter it and redistribute it 9 | # freely, subject to the following restrictions: 10 | # 11 | # 1. The origin of this software must not be misrepresented; you must not 12 | # claim that you wrote the original software. If you use this software 13 | # in a product, an acknowledgement in the product documentation would be 14 | # appreciated but is not required. 15 | # 2. Altered source versions must be plainly marked as such, and must not be 16 | # misrepresented as being the original software. 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | 19 | import sys, os 20 | 21 | if len(sys.argv) >= 2: 22 | sys.path.append(os.path.abspath(sys.argv[1])) 23 | else: 24 | filepath = os.path.dirname(__file__) 25 | guesspath = os.path.abspath(os.path.join(filepath, os.pardir)) 26 | guesspath = os.path.abspath(os.path.join(guesspath, os.pardir)) 27 | sys.path.append(guesspath) 28 | 29 | try: 30 | import pyfluid 31 | except ImportError: 32 | errmsg = ("Could not find the pyfluid package. Pass the directory that contains the " + 33 | "pyfluid package as a command line argument and try again. " + 34 | "For example, if the package is located at 'build/fluidsim/pyfluid', " + 35 | "then pass the directory 'build/fluidsim/'\n\n" + 36 | "Usage:\tpython example_inflow_outflow.py path/to/directory\n") 37 | raise ImportError(errmsg) 38 | 39 | # This example will add an inflow fluid source whose 40 | # position oscillates between two points. 41 | # 42 | # An outflow fluid source will be placed at one end of 43 | # the simulation domain to drain fluid. 44 | # 45 | # A solid pillar will be placed in the center of the 46 | # simulation domain. 47 | import math 48 | from pyfluid import FluidSimulation, CuboidFluidSource, AABB, Vector3, GridIndex 49 | 50 | def get_pillar_cells(position, radius, isize, jsize, ksize, dx): 51 | rsq = radius*radius 52 | cells = [] 53 | for k in range(ksize): 54 | for j in range(jsize): 55 | for i in range(isize): 56 | vx = (i + 0.5)*dx - position.x 57 | vz = (k + 0.5)*dx - position.z 58 | distsq = vx*vx + vz*vz 59 | if distsq < rsq: 60 | cells.append(GridIndex(i, j, k)) 61 | 62 | return cells 63 | 64 | 65 | isize = 128 66 | jsize = 64 67 | ksize = 64 68 | dx = 0.125 69 | fluidsim = FluidSimulation(isize, jsize, ksize, dx) 70 | 71 | width, height, depth = fluidsim.get_simulation_dimensions() 72 | 73 | # initialize fluid sources 74 | inflow_bbox = AABB() 75 | inflow_bbox.position = Vector3(0.0, 0.0, 0.0) 76 | inflow_bbox.width = 5*dx 77 | inflow_bbox.height = 15*dx 78 | inflow_bbox.depth = 30*dx 79 | inflow_velocity = Vector3(10.0, 0.0, 0.0) 80 | fluid_inflow = CuboidFluidSource(inflow_bbox, inflow_velocity) 81 | fluid_inflow.is_inflow = True 82 | 83 | outflow_bbox = AABB() 84 | outflow_bbox.position = Vector3(width - 5*dx, 0.0, 0.0) 85 | outflow_bbox.width = 10*dx 86 | outflow_bbox.height = height 87 | outflow_bbox.depth = depth 88 | fluid_outflow = CuboidFluidSource(outflow_bbox) 89 | fluid_outflow.is_outflow = True 90 | 91 | fluidsim.add_cuboid_fluid_source(fluid_inflow) 92 | fluidsim.add_cuboid_fluid_source(fluid_outflow) 93 | 94 | # Create a pillar of solid cells in the center of the domain 95 | center = Vector3(0.5*width, 0.5*height, 0.5*depth) 96 | radius = 10*dx 97 | pillar_cells = get_pillar_cells(center, radius, isize, jsize, ksize, dx) 98 | fluidsim.add_solid_cells(pillar_cells) 99 | 100 | fluidsim.add_body_force(0.0, -25.0, 0.0) 101 | fluidsim.initialize() 102 | 103 | timestep = 1.0/30.0 104 | runtime = 0.0 105 | while True: 106 | # Oscillate position of inflow source between two points 107 | runtime += timestep 108 | occspeed = 0.5*3.14159 109 | sinval = 0.5 + 0.5*math.sin(runtime*occspeed) 110 | 111 | p1 = Vector3(0.1*width, 0.15*height, 0.5*depth) 112 | p2 = Vector3(0.1*width, 0.85*height, 0.5*depth) 113 | p12 = p2 - p1 114 | sourcepos = p1 + sinval*p12 115 | fluid_inflow.center = sourcepos 116 | 117 | fluidsim.update(timestep) 118 | -------------------------------------------------------------------------------- /src/examples/python/example_lego_sphere_drop.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Ryan L. Guy 2 | # 3 | # This software is provided 'as-is', without any express or implied 4 | # warranty. In no event will the authors be held liable for any damages 5 | # arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, 8 | # including commercial applications, and to alter it and redistribute it 9 | # freely, subject to the following restrictions: 10 | # 11 | # 1. The origin of this software must not be misrepresented; you must not 12 | # claim that you wrote the original software. If you use this software 13 | # in a product, an acknowledgement in the product documentation would be 14 | # appreciated but is not required. 15 | # 2. Altered source versions must be plainly marked as such, and must not be 16 | # misrepresented as being the original software. 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | 19 | import sys, os 20 | 21 | if len(sys.argv) >= 2: 22 | sys.path.append(os.path.abspath(sys.argv[1])) 23 | else: 24 | filepath = os.path.dirname(__file__) 25 | guesspath = os.path.abspath(os.path.join(filepath, os.pardir)) 26 | guesspath = os.path.abspath(os.path.join(guesspath, os.pardir)) 27 | sys.path.append(guesspath) 28 | 29 | try: 30 | import pyfluid 31 | except ImportError: 32 | errmsg = ("Could not find the pyfluid package. Pass the directory that contains the " + 33 | "pyfluid package as a command line argument and try again. " + 34 | "For example, if the package is located at 'build/fluidsim/pyfluid', " + 35 | "then pass the directory 'build/fluidsim/'\n\n" + 36 | "Usage:\tpython example_lego_sphere_drop.py path/to/directory\n") 37 | raise ImportError(errmsg) 38 | 39 | # This example will drop a ball of fluid to a pool of resting fluid. The output 40 | # surface mesh will be generated as LEGO bricks. 41 | # 42 | # The brick surface reconstruction method requires data from three consecutive 43 | # frames, so data output will not be written to disk until the third frame. 44 | 45 | from pyfluid import FluidSimulation, AABB 46 | 47 | isize = 128 48 | jsize = 128 49 | ksize = 128 50 | dx = 0.0625 51 | fluidsim = FluidSimulation(isize, jsize, ksize, dx) 52 | 53 | fluidsim.enable_isotropic_surface_reconstruction = False 54 | 55 | brick = AABB() 56 | brick.width = 3*dx 57 | brick.height = 1.2*brick.width 58 | brick.depth = brick.width 59 | fluidsim.enable_brick_output = (True, brick) 60 | 61 | width, height, depth = fluidsim.get_simulation_dimensions() 62 | fluidsim.add_implicit_fluid_point(width/2, height/2, depth/2, 5.0) 63 | 64 | cuboid = AABB(0.0, 0.0, 0.0, width, 0.125*height, depth); 65 | fluidsim.add_fluid_cuboid(cuboid) 66 | 67 | fluidsim.add_body_force(0.0, -25.0, 0.0) 68 | fluidsim.initialize() 69 | 70 | timestep = 1.0/30.0 71 | while True: 72 | fluidsim.update(timestep) 73 | -------------------------------------------------------------------------------- /src/examples/python/example_save_load_state.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Ryan L. Guy 2 | # 3 | # This software is provided 'as-is', without any express or implied 4 | # warranty. In no event will the authors be held liable for any damages 5 | # arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, 8 | # including commercial applications, and to alter it and redistribute it 9 | # freely, subject to the following restrictions: 10 | # 11 | # 1. The origin of this software must not be misrepresented; you must not 12 | # claim that you wrote the original software. If you use this software 13 | # in a product, an acknowledgement in the product documentation would be 14 | # appreciated but is not required. 15 | # 2. Altered source versions must be plainly marked as such, and must not be 16 | # misrepresented as being the original software. 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | 19 | import sys, os 20 | 21 | if len(sys.argv) >= 2: 22 | sys.path.append(os.path.abspath(sys.argv[1])) 23 | else: 24 | filepath = os.path.dirname(__file__) 25 | guesspath = os.path.abspath(os.path.join(filepath, os.pardir)) 26 | guesspath = os.path.abspath(os.path.join(guesspath, os.pardir)) 27 | sys.path.append(guesspath) 28 | 29 | try: 30 | import pyfluid 31 | except ImportError: 32 | errmsg = ("Could not find the pyfluid package. Pass the directory that contains the " + 33 | "pyfluid package as a command line argument and try again. " + 34 | "For example, if the package is located at 'build/fluidsim/pyfluid', " + 35 | "then pass the directory 'build/fluidsim/'\n\n" + 36 | "Usage:\tpython example_save_load_state.py path/to/directory\n") 37 | raise ImportError(errmsg) 38 | 39 | 40 | # The fluid simulator generates an autosave state at the start of each frame 41 | # by default. 42 | # 43 | # This example will turn off the autosave feature and demonstrate how to 44 | # manually save and load a savestate. 45 | 46 | from pyfluid import FluidSimulation, FluidSimulationSaveState 47 | from pyfluid import config 48 | 49 | def save_state(filename): 50 | isize = 64 51 | jsize = 64 52 | ksize = 64 53 | dx = 0.125 54 | fluidsim = FluidSimulation(isize, jsize, ksize, dx) 55 | 56 | width, height, depth = fluidsim.get_simulation_dimensions() 57 | fluidsim.add_implicit_fluid_point(width/2, 0.0, depth/2, 7.0) 58 | 59 | fluidsim.add_body_force(0.0, -25.0, 0.0) 60 | fluidsim.enable_autosave = False 61 | fluidsim.initialize() 62 | 63 | timestep = 1.0 / 30.0 64 | num_frames = 5 65 | for i in range(num_frames): 66 | fluidsim.update(timestep) 67 | 68 | fluidsim.save_state(filename) 69 | 70 | def load_state(filename): 71 | state = FluidSimulationSaveState(); 72 | success = state.load_state(filename) 73 | 74 | if not success: 75 | raise RuntimeError("Unable to load savestate: " + filename) 76 | 77 | fluidsim = FluidSimulation.from_save_state(state) 78 | 79 | # After constructing the FluidSimulation object, the save state is 80 | # no longer needed and can be closed. Closing the state will 81 | # clean up any temporary files that were created during loading 82 | # the state and initializing the fluid simulation. 83 | state.close_state() 84 | 85 | # The save state feature only saves the following data: 86 | # - grid dimensions and cell size 87 | # - current frame 88 | # - marker particles 89 | # - diffuse particles 90 | # - solid cells 91 | # - FluidBrickGrid data 92 | # 93 | # The save state will not load any changed settings, body forces, 94 | # or fluid sources, so these attributes/objects will need to be re-added 95 | # manually if desired once the state is loaded. 96 | 97 | # The initialize() method does not need to be called when loading a simulation 98 | # from a save state. The simulation is initialized within the constructor. 99 | 100 | fluidsim.add_body_force(0.0, -25.0, 0.0) 101 | fluidsim.enable_autosave = False 102 | 103 | timestep = 1.0 / 30.0 104 | num_frames = 5 105 | for i in range(num_frames): 106 | fluidsim.update(timestep) 107 | 108 | 109 | def main(): 110 | directory = config.get_savestates_directory() 111 | filename = directory + "/mySaveState.state" 112 | save_state(filename) 113 | load_state(filename) 114 | 115 | if __name__ == "__main__": 116 | main() -------------------------------------------------------------------------------- /src/examples/python/example_sphere_drop.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016 Ryan L. Guy 2 | # 3 | # This software is provided 'as-is', without any express or implied 4 | # warranty. In no event will the authors be held liable for any damages 5 | # arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, 8 | # including commercial applications, and to alter it and redistribute it 9 | # freely, subject to the following restrictions: 10 | # 11 | # 1. The origin of this software must not be misrepresented; you must not 12 | # claim that you wrote the original software. If you use this software 13 | # in a product, an acknowledgement in the product documentation would be 14 | # appreciated but is not required. 15 | # 2. Altered source versions must be plainly marked as such, and must not be 16 | # misrepresented as being the original software. 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | 19 | import sys, os 20 | 21 | if len(sys.argv) >= 2: 22 | sys.path.append(os.path.abspath(sys.argv[1])) 23 | else: 24 | filepath = os.path.dirname(__file__) 25 | guesspath = os.path.abspath(os.path.join(filepath, os.pardir)) 26 | guesspath = os.path.abspath(os.path.join(guesspath, os.pardir)) 27 | sys.path.append(guesspath) 28 | 29 | try: 30 | import pyfluid 31 | except ImportError: 32 | errmsg = ("Could not find the pyfluid package. Pass the directory that contains the " + 33 | "pyfluid package as a command line argument and try again. " + 34 | "For example, if the package is located at 'build/fluidsim/pyfluid', " + 35 | "then pass the directory 'build/fluidsim/'\n\n" + 36 | "Usage:\tpython example_sphere_drop.py path/to/directory\n") 37 | raise ImportError(errmsg) 38 | 39 | # This example will drop a ball of fluid in the center 40 | # of a rectangular fluid simulation domain. 41 | from pyfluid import FluidSimulation 42 | 43 | isize = 256 44 | jsize = 128 45 | ksize = 128 46 | dx = 0.0625 47 | fluidsim = FluidSimulation(isize, jsize, ksize, dx) 48 | 49 | # Increase subdivision level to increase the resolution that 50 | # the output meshes are generated at. 51 | fluidsim.surface_subdivision_level = 1 52 | 53 | if fluidsim.surface_subdivision_level >= 2: 54 | # Helps reduce output filesize by removing polyhedrons 55 | # that do not meet a minimum triangle count threshold. 56 | fluidsim.minimum_polyhedron_triangle_count = 64 57 | 58 | width, height, depth = fluidsim.get_simulation_dimensions() 59 | fluidsim.add_implicit_fluid_point(width/2, height/2, depth/2, 7.0) 60 | 61 | fluidsim.add_body_force(0.0, -25.0, 0.0) 62 | fluidsim.initialize() 63 | 64 | timestep = 1.0/30.0 65 | while True: 66 | fluidsim.update(timestep) 67 | -------------------------------------------------------------------------------- /src/fluidbrickgridsavestate.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef FLUIDBRICKGRIDSAVESTATE_H 21 | #define FLUIDBRICKGRIDSAVESTATE_H 22 | 23 | #include 24 | #include 25 | 26 | #include "array3d.h" 27 | #include "vmath.h" 28 | #include "aabb.h" 29 | #include "brick.h" 30 | #include "fluidsimassert.h" 31 | 32 | class FluidBrickGrid; 33 | 34 | class FluidBrickGridSaveState 35 | { 36 | public: 37 | FluidBrickGridSaveState(); 38 | ~FluidBrickGridSaveState(); 39 | 40 | void saveState(std::string filename, FluidBrickGrid *brickgrid); 41 | bool loadState(std::string filename); 42 | void closeState(); 43 | 44 | bool isLoadStateInitialized(); 45 | void getGridDimensions(int *i, int *j, int *k); 46 | void getBrickGridDimensions(int *bi, int *bj, int *bk); 47 | double getCellSize(); 48 | AABB getBrickAABB(); 49 | int getBrickGridQueueSize(); 50 | int getNumUpdates(); 51 | void getCurrentDensityGrid(Array3d &grid); 52 | void getTargetDensityGrid(Array3d &grid); 53 | void getVelocityDensityGrid(Array3d &grid); 54 | void getBrickActivityGrid(Array3d &grid, int idx); 55 | void getBrickIntensityGrid(Array3d &grid, int idx); 56 | 57 | private: 58 | 59 | void _writeInt(int *value, std::ofstream *state); 60 | void _writeDouble(double *value, std::ofstream *state); 61 | void _writeBinaryDensityGrid(FluidBrickGrid *brickgrid, 62 | std::ofstream *state); 63 | void _writeBinaryBrickGridQueue(FluidBrickGrid *brickgrid, 64 | std::ofstream *state); 65 | void _writeBinaryBrickGrid(Array3d *grid, 66 | std::ofstream *state); 67 | void _writeBinaryArray3df(Array3d &grid, 68 | std::ofstream *state); 69 | void _writeBinaryArray3db(Array3d &grid, 70 | std::ofstream *state); 71 | 72 | void _setLoadStateFileOffset(unsigned int foffset); 73 | bool _readInt(int *value, std::ifstream *state); 74 | bool _readDouble(double *value, std::ifstream *state); 75 | void _getBrickGridDimensions(int *bi, int *bj, int *bk); 76 | bool _readLoadState(char *dest, unsigned int numBytes); 77 | 78 | std::ifstream _loadState; 79 | 80 | int _isize = 0; 81 | int _jsize = 0; 82 | int _ksize = 0; 83 | double _dx = 0.0; 84 | AABB _brickAABB; 85 | int _brickGridQueueSize = 0; 86 | int _numUpdates = 0; 87 | 88 | unsigned int _currentDensityOffset = 0; 89 | unsigned int _targetDensityOffset = 0; 90 | unsigned int _velocityDensityOffset = 0; 91 | unsigned int _brickGridOffset1 = 0; 92 | unsigned int _brickGridOffset2 = 0; 93 | unsigned int _brickGridOffset3 = 0; 94 | unsigned int _eofOffset = 0; 95 | unsigned int _currentOffset = 0; 96 | 97 | bool _isLoadStateInitialized = false; 98 | }; 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /src/fluidmaterialgrid.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef FLUIDMATERIALGRID_H 21 | #define FLUIDMATERIALGRID_H 22 | 23 | #include 24 | 25 | #include "subdividedarray3d.h" 26 | #include "grid3d.h" 27 | #include "gridindexvector.h" 28 | 29 | enum class Material : char { 30 | air = 0x00, 31 | fluid = 0x01, 32 | solid = 0x02 33 | }; 34 | 35 | class FluidMaterialGrid { 36 | 37 | public: 38 | 39 | FluidMaterialGrid(); 40 | FluidMaterialGrid(int i, int j, int k); 41 | ~FluidMaterialGrid(); 42 | 43 | Material operator()(int i, int j, int k); 44 | Material operator()(GridIndex g); 45 | 46 | void fill(Material m); 47 | 48 | void set(int i, int j, int k, Material m); 49 | void set(GridIndex g, Material m); 50 | void set(GridIndexVector &cells, Material m); 51 | void setAir(int i, int j, int k); 52 | void setAir(GridIndex g); 53 | void setAir(GridIndexVector &cells); 54 | void setFluid(int i, int j, int k); 55 | void setFluid(GridIndex g); 56 | void setFluid(GridIndexVector &cells); 57 | void setSolid(int i, int j, int k); 58 | void setSolid(GridIndex g); 59 | void setSolid(GridIndexVector &cells); 60 | 61 | bool isCellAir(int i, int j, int k); 62 | bool isCellAir(GridIndex g); 63 | bool isCellFluid(int i, int j, int k); 64 | bool isCellFluid(GridIndex g); 65 | bool isCellSolid(int i, int j, int k); 66 | bool isCellSolid(GridIndex g); 67 | 68 | bool isFaceBorderingMaterialU(int i, int j, int k, Material m); 69 | bool isFaceBorderingMaterialU(GridIndex g, Material m); 70 | bool isFaceBorderingMaterialV(int i, int j, int k, Material m); 71 | bool isFaceBorderingMaterialV(GridIndex g, Material m); 72 | bool isFaceBorderingMaterialW(int i, int j, int k, Material m); 73 | bool isFaceBorderingMaterialW(GridIndex g, Material m); 74 | bool isFaceBorderingAirU(int i, int j, int k); 75 | bool isFaceBorderingAirU(GridIndex g); 76 | bool isFaceBorderingFluidU(int i, int j, int k); 77 | bool isFaceBorderingFluidU(GridIndex g); 78 | bool isFaceBorderingSolidU(int i, int j, int k); 79 | bool isFaceBorderingSolidU(GridIndex g); 80 | bool isFaceBorderingAirV(int i, int j, int k); 81 | bool isFaceBorderingAirV(GridIndex g); 82 | bool isFaceBorderingFluidV(int i, int j, int k); 83 | bool isFaceBorderingFluidV(GridIndex g); 84 | bool isFaceBorderingSolidV(int i, int j, int k); 85 | bool isFaceBorderingSolidV(GridIndex g); 86 | bool isFaceBorderingAirW(int i, int j, int k); 87 | bool isFaceBorderingAirW(GridIndex g); 88 | bool isFaceBorderingFluidW(int i, int j, int k); 89 | bool isFaceBorderingFluidW(GridIndex g); 90 | bool isFaceBorderingSolidW(int i, int j, int k); 91 | bool isFaceBorderingSolidW(GridIndex g); 92 | 93 | bool isCellNeighbouringMaterial(int i, int j, int k, Material m); 94 | bool isCellNeighbouringMaterial(GridIndex g, Material m); 95 | bool isCellNeighbouringAir(int i, int j, int k); 96 | bool isCellNeighbouringAir(GridIndex g); 97 | bool isCellNeighbouringFluid(int i, int j, int k); 98 | bool isCellNeighbouringFluid(GridIndex g); 99 | bool isCellNeighbouringSolid(int i, int j, int k); 100 | bool isCellNeighbouringSolid(GridIndex g); 101 | 102 | void setSubdivisionLevel(int n); 103 | int getSubdivisionLevel(); 104 | 105 | int width = 0; 106 | int height = 0; 107 | int depth = 0; 108 | 109 | private: 110 | 111 | SubdividedArray3d _grid; 112 | 113 | 114 | }; 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /src/fluidsimassert.h: -------------------------------------------------------------------------------- 1 | #ifndef NFLUIDSIMDEBUG 2 | #include 3 | #include 4 | #define FLUIDSIM_ASSERT(condition)\ 5 | {\ 6 | if (!(condition))\ 7 | {\ 8 | std::cerr << "Assertion failed: " << #condition <<\ 9 | ", file " << __FILE__ <<\ 10 | ", function " << __FUNCTION__ <<\ 11 | ", line " << __LINE__ << std::endl;\ 12 | abort();\ 13 | }\ 14 | } 15 | #else 16 | #define FLUIDSIM_ASSERT(condition) (condition) 17 | #endif 18 | -------------------------------------------------------------------------------- /src/fluidsource.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "fluidsource.h" 21 | 22 | int FluidSource::_IDCounter = 0; 23 | 24 | FluidSource::FluidSource() { 25 | _initializeID(); 26 | } 27 | 28 | FluidSource::FluidSource(vmath::vec3 vel) : _velocity(vel), 29 | _direction(vmath::normalize(_velocity)) { 30 | if (!(vmath::length(_velocity) > 0.0)) { 31 | _direction = vmath::vec3(1.0, 0.0, 0.0); 32 | } 33 | _initializeID(); 34 | } 35 | 36 | 37 | FluidSource::~FluidSource() { 38 | } 39 | 40 | vmath::vec3 FluidSource::getVelocity() { 41 | return _velocity; 42 | } 43 | 44 | void FluidSource::setVelocity(vmath::vec3 v) { 45 | _velocity = v; 46 | if (vmath::length(v) > 0.0) { 47 | _direction = vmath::normalize(v); 48 | } else { 49 | _direction = vmath::vec3(1.0, 0.0, 0.0); 50 | } 51 | } 52 | 53 | vmath::vec3 FluidSource::getDirection() { 54 | return _direction; 55 | } 56 | 57 | void FluidSource::setDirection(vmath::vec3 dir) { 58 | float length = vmath::length(dir); 59 | if (!(length > 0.0f)) { 60 | return; 61 | } 62 | 63 | _direction = vmath::normalize(dir); 64 | _velocity = vmath::length(_velocity) * _direction; 65 | } 66 | 67 | void FluidSource::setAsInflow() { 68 | _sourceType = FluidSourceType::inflow; 69 | } 70 | 71 | void FluidSource::setAsOutflow() { 72 | _sourceType = FluidSourceType::outflow; 73 | } 74 | 75 | FluidSourceType FluidSource::getSourceType() { 76 | return _sourceType; 77 | } 78 | 79 | bool FluidSource::isInflow() { 80 | return _sourceType == FluidSourceType::inflow; 81 | } 82 | 83 | bool FluidSource::isOutflow() { 84 | return _sourceType == FluidSourceType::outflow; 85 | } 86 | 87 | void FluidSource::activate() { 88 | _isActive = true; 89 | } 90 | 91 | void FluidSource::deactivate() { 92 | _isActive = false; 93 | } 94 | 95 | bool FluidSource::isActive() { 96 | return _isActive; 97 | } 98 | 99 | GridIndexVector FluidSource::getAirCells(FluidMaterialGrid &materialGrid, 100 | double dx) { 101 | int w = materialGrid.width; 102 | int h = materialGrid.height; 103 | int d = materialGrid.depth; 104 | GridIndexVector cells(w, h, d); 105 | 106 | if (!isActive()) { 107 | return cells; 108 | } 109 | 110 | GridIndexVector overlappingIndices(w, h, d); 111 | _getOverlappingCells(overlappingIndices, dx); 112 | 113 | GridIndex g; 114 | for (unsigned int i = 0; i < overlappingIndices.size(); i++) { 115 | g = overlappingIndices[i]; 116 | if (materialGrid.isCellAir(g)) { 117 | cells.push_back(g); 118 | } 119 | } 120 | 121 | return cells; 122 | } 123 | 124 | GridIndexVector FluidSource::getFluidCells(FluidMaterialGrid &materialGrid, 125 | double dx) { 126 | int w = materialGrid.width; 127 | int h = materialGrid.height; 128 | int d = materialGrid.depth; 129 | GridIndexVector cells(w, h, d); 130 | 131 | if (!isActive()) { 132 | return cells; 133 | } 134 | 135 | GridIndexVector overlappingIndices(w, h, d); 136 | _getOverlappingCells(overlappingIndices, dx); 137 | 138 | GridIndex g; 139 | for (unsigned int i = 0; i < overlappingIndices.size(); i++) { 140 | g = overlappingIndices[i]; 141 | if (materialGrid.isCellFluid(g)) { 142 | cells.push_back(g); 143 | } 144 | } 145 | 146 | return cells; 147 | } 148 | 149 | GridIndexVector FluidSource::getFluidOrAirCells(FluidMaterialGrid &materialGrid, 150 | double dx) { 151 | int w = materialGrid.width; 152 | int h = materialGrid.height; 153 | int d = materialGrid.depth; 154 | GridIndexVector cells(w, h, d); 155 | 156 | if (!isActive()) { 157 | return cells; 158 | } 159 | 160 | GridIndexVector overlappingIndices(w, h, d); 161 | _getOverlappingCells(overlappingIndices, dx); 162 | 163 | GridIndex g; 164 | for (unsigned int i = 0; i < overlappingIndices.size(); i++) { 165 | g = overlappingIndices[i]; 166 | if (!materialGrid.isCellSolid(g)) { 167 | cells.push_back(g); 168 | } 169 | } 170 | 171 | return cells; 172 | } 173 | 174 | int FluidSource::getID() { 175 | return _ID; 176 | } 177 | 178 | void FluidSource::_initializeID() { 179 | _ID = _IDCounter++; 180 | } -------------------------------------------------------------------------------- /src/fluidsource.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef FLUIDSOURCE_H 21 | #define FLUIDSOURCE_H 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "vmath.h" 28 | #include "array3d.h" 29 | #include "grid3d.h" 30 | #include "aabb.h" 31 | #include "fluidmaterialgrid.h" 32 | #include "gridindexvector.h" 33 | 34 | enum class FluidSourceType : char { 35 | inflow = 0x00, 36 | outflow = 0x01 37 | }; 38 | 39 | class FluidSource 40 | { 41 | public: 42 | FluidSource(); 43 | FluidSource(vmath::vec3 velocity); 44 | virtual ~FluidSource(); 45 | 46 | virtual vmath::vec3 getPosition() = 0; 47 | virtual void setPosition(vmath::vec3 pos) = 0; 48 | virtual AABB getAABB() = 0; 49 | virtual bool containsPoint(vmath::vec3 p) = 0; 50 | 51 | vmath::vec3 getVelocity(); 52 | void setVelocity(vmath::vec3 v); 53 | vmath::vec3 getDirection(); 54 | void setDirection(vmath::vec3 dir); 55 | void setAsInflow(); 56 | void setAsOutflow(); 57 | FluidSourceType getSourceType(); 58 | bool isInflow(); 59 | bool isOutflow(); 60 | void activate(); 61 | void deactivate(); 62 | bool isActive(); 63 | int getID(); 64 | 65 | GridIndexVector getAirCells(FluidMaterialGrid &materialGrid, double dx); 66 | GridIndexVector getFluidCells(FluidMaterialGrid &materialGrid, double dx); 67 | GridIndexVector getFluidOrAirCells(FluidMaterialGrid &materialGrid, double dx); 68 | 69 | protected: 70 | virtual void _getOverlappingCells(GridIndexVector &storage, double dx) = 0; 71 | 72 | private: 73 | void _initializeID(); 74 | 75 | vmath::vec3 _velocity; 76 | vmath::vec3 _direction; 77 | bool _isActive = true; 78 | FluidSourceType _sourceType = FluidSourceType::inflow; 79 | int _ID; 80 | 81 | static int _IDCounter; 82 | }; 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /src/gridindexkeymap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "gridindexkeymap.h" 21 | 22 | GridIndexKeyMap::GridIndexKeyMap() { 23 | } 24 | 25 | GridIndexKeyMap::GridIndexKeyMap(int i, int j, int k) : _isize(i), _jsize(j), _ksize(k) { 26 | _indices = std::vector(i*j*k, _notFoundValue); 27 | } 28 | 29 | GridIndexKeyMap::~GridIndexKeyMap() { 30 | } 31 | 32 | void GridIndexKeyMap::clear() { 33 | for (unsigned int i = 0; i < _indices.size(); i++) { 34 | _indices[i] = _notFoundValue; 35 | } 36 | } 37 | 38 | void GridIndexKeyMap::insert(GridIndex g, int key) { 39 | insert(g.i, g.j, g.k, key); 40 | } 41 | 42 | void GridIndexKeyMap::insert(int i, int j, int k, int key) { 43 | FLUIDSIM_ASSERT(Grid3d::isGridIndexInRange(i, j, k, _isize, _jsize, _ksize)); 44 | 45 | int flatidx = _getFlatIndex(i, j, k); 46 | _indices[flatidx] = key; 47 | } 48 | 49 | int GridIndexKeyMap::find(GridIndex g) { 50 | return find(g.i, g.j, g.k); 51 | } 52 | 53 | int GridIndexKeyMap::find(int i, int j, int k) { 54 | FLUIDSIM_ASSERT(Grid3d::isGridIndexInRange(i, j, k, _isize, _jsize, _ksize)); 55 | 56 | if (_indices.size() == 0) { 57 | return _notFoundValue; 58 | } 59 | 60 | int flatidx = _getFlatIndex(i, j, k); 61 | return _indices[flatidx]; 62 | } 63 | -------------------------------------------------------------------------------- /src/gridindexkeymap.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef GRIDINDEXKEYMAP_H 21 | #define GRIDINDEXKEYMAP_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "grid3d.h" 30 | #include "array3d.h" 31 | #include "fluidsimassert.h" 32 | 33 | class GridIndexKeyMap 34 | { 35 | public: 36 | GridIndexKeyMap(); 37 | GridIndexKeyMap(int i, int j, int k); 38 | ~GridIndexKeyMap(); 39 | 40 | void clear(); 41 | void insert(GridIndex g, int key); 42 | void insert(int i, int j, int k, int key); 43 | int find(GridIndex g); 44 | int find(int i, int j, int k); 45 | 46 | private: 47 | 48 | inline unsigned int _getFlatIndex(int i, int j, int k) { 49 | return (unsigned int)i + (unsigned int)_isize * 50 | ((unsigned int)j + (unsigned int)_jsize * (unsigned int)k); 51 | } 52 | 53 | inline unsigned int _getFlatIndex(GridIndex g) { 54 | return (unsigned int)g.i + (unsigned int)_isize * 55 | ((unsigned int)g.j + (unsigned int)_jsize * (unsigned int)g.k); 56 | } 57 | 58 | int _isize = 0; 59 | int _jsize = 0; 60 | int _ksize = 0; 61 | 62 | std::vector _indices; 63 | int _notFoundValue = -1; 64 | 65 | }; 66 | 67 | #endif -------------------------------------------------------------------------------- /src/gridindexvector.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "gridindexvector.h" 21 | 22 | GridIndexVector::GridIndexVector() { 23 | } 24 | 25 | GridIndexVector::GridIndexVector(int i, int j, int k) : 26 | width(i), height(j), depth(k) { 27 | } 28 | 29 | GridIndexVector::~GridIndexVector() { 30 | } 31 | 32 | 33 | GridIndex GridIndexVector::operator[](int i) { 34 | FLUIDSIM_ASSERT(i >= 0 && i < (int)_indices.size()); 35 | return _getUnflattenedIndex(_indices[i]); 36 | } 37 | 38 | void GridIndexVector::insert(std::vector &indices) { 39 | reserve(_indices.size() + indices.size()); 40 | for (unsigned int i = 0; i < indices.size(); i++) { 41 | push_back(indices[i]); 42 | } 43 | } 44 | 45 | void GridIndexVector::insert(GridIndexVector &indices) { 46 | FLUIDSIM_ASSERT(width == indices.width && height == indices.height && depth == indices.depth); 47 | 48 | reserve(_indices.size() + indices.size()); 49 | int maxidx = width*height*depth - 1; 50 | for (unsigned int i = 0; i < indices.size(); i++) { 51 | int flatidx = indices.getFlatIndex(i); 52 | FLUIDSIM_ASSERT(flatidx >= 0 && flatidx <= maxidx); 53 | _indices.push_back(flatidx); 54 | } 55 | } 56 | 57 | std::vector GridIndexVector::getVector() { 58 | std::vector vector; 59 | vector.reserve(size()); 60 | 61 | for (unsigned int i = 0; i < size(); i++) { 62 | vector.push_back((*this)[i]); 63 | } 64 | 65 | return vector; 66 | } 67 | 68 | void GridIndexVector::getVector(std::vector &vector) { 69 | vector.reserve(size()); 70 | 71 | for (unsigned int i = 0; i < size(); i++) { 72 | vector.push_back((*this)[i]); 73 | } 74 | } -------------------------------------------------------------------------------- /src/gridindexvector.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef GRIDINDEXVECTOR_H 21 | #define GRIDINDEXVECTOR_H 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "array3d.h" 28 | #include "fluidsimassert.h" 29 | 30 | class GridIndexVector 31 | { 32 | public: 33 | GridIndexVector(); 34 | GridIndexVector(int i, int j, int k); 35 | ~GridIndexVector(); 36 | 37 | inline size_t size() { 38 | return _indices.size(); 39 | } 40 | 41 | inline bool empty() { 42 | return _indices.empty(); 43 | } 44 | 45 | inline void reserve(size_t n) { 46 | _indices.reserve(n); 47 | } 48 | 49 | inline void shrink_to_fit() { 50 | _indices.shrink_to_fit(); 51 | } 52 | 53 | GridIndex operator[](int i); 54 | 55 | inline GridIndex at(int i) { 56 | FLUIDSIM_ASSERT(i >= 0 && i < (int)_indices.size()); 57 | return _getUnflattenedIndex(_indices[i]); 58 | } 59 | 60 | inline GridIndex get(int i) { 61 | FLUIDSIM_ASSERT(i >= 0 && i < (int)_indices.size()); 62 | return _getUnflattenedIndex(_indices[i]); 63 | } 64 | 65 | inline unsigned int getFlatIndex(int i) { 66 | FLUIDSIM_ASSERT(i >= 0 && i < (int)_indices.size()); 67 | return _indices[i]; 68 | } 69 | 70 | inline GridIndex front() { 71 | FLUIDSIM_ASSERT(!_indices.empty()); 72 | return _getUnflattenedIndex(_indices.front()); 73 | } 74 | 75 | inline GridIndex back() { 76 | FLUIDSIM_ASSERT(!_indices.empty()); 77 | return _getUnflattenedIndex(_indices.back()); 78 | } 79 | 80 | inline void push_back(GridIndex g) { 81 | FLUIDSIM_ASSERT(g.i >= 0 && g.j >= 0 && g.k >= 0 && g.i < width && g.j < height && g.k < depth); 82 | _indices.push_back(_getFlatIndex(g)); 83 | } 84 | 85 | inline void push_back(int i, int j, int k) { 86 | FLUIDSIM_ASSERT(i >= 0 && j >= 0 && k >= 0 && i < width && j < height && k < depth); 87 | _indices.push_back(_getFlatIndex(i, j, k)); 88 | } 89 | 90 | void insert(std::vector &indices); 91 | void insert(GridIndexVector &indices); 92 | 93 | inline void pop_back() { 94 | FLUIDSIM_ASSERT(!_indices.empty()); 95 | _indices.pop_back(); 96 | } 97 | 98 | inline void clear() { 99 | _indices.clear(); 100 | } 101 | 102 | std::vector getVector(); 103 | void getVector(std::vector &vector); 104 | 105 | int width = 0; 106 | int height = 0; 107 | int depth = 0; 108 | 109 | private: 110 | 111 | inline unsigned int _getFlatIndex(int i, int j, int k) { 112 | return (unsigned int)i + (unsigned int)width * 113 | ((unsigned int)j + (unsigned int)height * (unsigned int)k); 114 | } 115 | 116 | inline unsigned int _getFlatIndex(GridIndex g) { 117 | return (unsigned int)g.i + (unsigned int)width * 118 | ((unsigned int)g.j + (unsigned int)height * (unsigned int)g.k); 119 | } 120 | 121 | inline GridIndex _getUnflattenedIndex(unsigned int flatidx) { 122 | int i = flatidx % width; 123 | int j = (flatidx / width) % height; 124 | int k = flatidx / (width * height); 125 | 126 | return GridIndex(i, j, k); 127 | } 128 | 129 | std::vector _indices; 130 | 131 | }; 132 | 133 | #endif -------------------------------------------------------------------------------- /src/implicitpointprimitive.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "implicitpointprimitive.h" 21 | 22 | ImplicitPointPrimitive::ImplicitPointPrimitive() { 23 | _initFieldFunctionCoefficients(); 24 | } 25 | 26 | ImplicitPointPrimitive::ImplicitPointPrimitive(double x, double y, double z, double r) : 27 | _position(x, y, z), _radius(r) 28 | { 29 | _initFieldFunctionCoefficients(); 30 | } 31 | 32 | ImplicitPointPrimitive::ImplicitPointPrimitive(vmath::vec3 p, double r) : 33 | _position(p), _radius(r) 34 | { 35 | _initFieldFunctionCoefficients(); 36 | } 37 | 38 | ImplicitPointPrimitive::~ImplicitPointPrimitive() 39 | { 40 | } 41 | 42 | void ImplicitPointPrimitive::_initFieldFunctionCoefficients() { 43 | double r = _radius; 44 | _coef1 = (4.0 / 9.0)*(1.0 / (r*r*r*r*r*r)); 45 | _coef2 = (17.0 / 9.0)*(1.0 / (r*r*r*r)); 46 | _coef3 = (22.0 / 9.0)*(1.0 / (r*r)); 47 | } 48 | 49 | double ImplicitPointPrimitive::getFieldValue(vmath::vec3 p) { 50 | vmath::vec3 v = p - _position; 51 | double distsq = vmath::dot(v, v); 52 | 53 | if (distsq > _radius*_radius) { 54 | return 0.0; 55 | } 56 | 57 | return _evaluateFieldFunction(sqrt(distsq)); 58 | } 59 | 60 | double ImplicitPointPrimitive::_evaluateFieldFunction(double r) { 61 | return 1.0 - _coef1*r*r*r*r*r*r + _coef2*r*r*r*r - _coef3*r*r; 62 | } 63 | -------------------------------------------------------------------------------- /src/implicitpointprimitive.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef IMPLICITPOINTPRIMITIVE_H 21 | #define IMPLICITPOINTPRIMITIVE_H 22 | 23 | #include 24 | #include 25 | 26 | #include "vmath.h" 27 | 28 | class ImplicitPointPrimitive 29 | { 30 | public: 31 | ImplicitPointPrimitive(); 32 | ImplicitPointPrimitive(double x, double y, double z, double r); 33 | ImplicitPointPrimitive(vmath::vec3 p, double r); 34 | ~ImplicitPointPrimitive(); 35 | 36 | void setPosition(double x, double y, double z) { _position = vmath::vec3(x, y, z); } 37 | void setPosition(vmath::vec3 p) { _position = p; } 38 | void setRadius(double r) { _radius = r; _initFieldFunctionCoefficients(); } 39 | void translate(double tx, double ty, double tz) { _position += vmath::vec3(tx, ty, tz); } 40 | void translate(vmath::vec3 t) { _position += t; } 41 | 42 | vmath::vec3 getPosition() { return _position; } 43 | void getPosition(double *x, double *y, double *z) { *x = _position.x; 44 | *y = _position.y; 45 | *z = _position.z; } 46 | double getRadius() { return _radius; } 47 | 48 | double getFieldValue(double x, double y, double z) { return getFieldValue(vmath::vec3(x, y, z)); }; 49 | double getFieldValue(vmath::vec3 p); 50 | 51 | private: 52 | void _initFieldFunctionCoefficients(); 53 | double _evaluateFieldFunction(double r); 54 | 55 | vmath::vec3 _position; 56 | double _radius = 1; 57 | 58 | double _coef1; 59 | double _coef2; 60 | double _coef3; 61 | 62 | }; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/interpolation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it 8 | freely, subject to the following restrictions: 9 | 1. The origin of this software must not be misrepresented; you must not 10 | claim that you wrote the original software. If you use this software 11 | in a product, an acknowledgement in the product documentation would be 12 | appreciated but is not required. 13 | 2. Altered source versions must be plainly marked as such, and must not be 14 | misrepresented as being the original software. 15 | 3. This notice may not be removed or altered from any source distribution. 16 | */ 17 | #include "interpolation.h" 18 | 19 | /* 20 | Cubic interpolation methods from http://www.paulinternet.nl/?page=bicubic 21 | 22 | - p is indexed in order by p[k][j][i] 23 | - x, y, z are in [0,1] 24 | - this function will interpolate the volume between point Index 1 and 2 25 | +*/ 26 | double Interpolation::tricubicInterpolate(double p[4][4][4], double x, double y, double z) { 27 | double arr[4]; 28 | arr[0] = bicubicInterpolate(p[0], x, y); 29 | arr[1] = bicubicInterpolate(p[1], x, y); 30 | arr[2] = bicubicInterpolate(p[2], x, y); 31 | arr[3] = bicubicInterpolate(p[3], x, y); 32 | return cubicInterpolate(arr, z); 33 | } 34 | 35 | double Interpolation::bicubicInterpolate(double p[4][4], double x, double y) { 36 | double arr[4]; 37 | arr[0] = cubicInterpolate(p[0], x); 38 | arr[1] = cubicInterpolate(p[1], x); 39 | arr[2] = cubicInterpolate(p[2], x); 40 | arr[3] = cubicInterpolate(p[3], x); 41 | return cubicInterpolate(arr, y); 42 | } 43 | 44 | double Interpolation::cubicInterpolate(double p[4], double x) { 45 | return p[1] + 0.5 * x*(p[2] - p[0] + x*(2.0*p[0] - 5.0*p[1] + 4.0*p[2] - p[3] + x*(3.0*(p[1] - p[2]) + p[3] - p[0]))); 46 | } 47 | 48 | // vertices p are ordered {(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1), 49 | // (1, 0, 1), (0, 1, 1), (1, 1, 0), (1, 1, 1)} 50 | // x, y, z, in range [0,1] 51 | double Interpolation::trilinearInterpolate(double p[8], double x, double y, double z) { 52 | return p[0] * (1 - x) * (1 - y) * (1 - z) + 53 | p[1] * x * (1 - y) * (1 - z) + 54 | p[2] * (1 - x) * y * (1 - z) + 55 | p[3] * (1 - x) * (1 - y) * z + 56 | p[4] * x * (1 - y) * z + 57 | p[5] * (1 - x) * y * z + 58 | p[6] * x * y * (1 - z) + 59 | p[7] * x * y * z; 60 | } -------------------------------------------------------------------------------- /src/interpolation.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | Permission is granted to anyone to use this software for any purpose, 7 | including commercial applications, and to alter it and redistribute it 8 | freely, subject to the following restrictions: 9 | 1. The origin of this software must not be misrepresented; you must not 10 | claim that you wrote the original software. If you use this software 11 | in a product, an acknowledgement in the product documentation would be 12 | appreciated but is not required. 13 | 2. Altered source versions must be plainly marked as such, and must not be 14 | misrepresented as being the original software. 15 | 3. This notice may not be removed or altered from any source distribution. 16 | */ 17 | #ifndef INTERPOLATION_H 18 | #define INTERPOLATION_H 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace Interpolation { 25 | 26 | extern double cubicInterpolate(double p[4], double x); 27 | extern double bicubicInterpolate(double p[4][4], double x, double y); 28 | extern double tricubicInterpolate(double p[4][4][4], double x, double y, double z); 29 | extern double trilinearInterpolate(double p[8], double x, double y, double z); 30 | } 31 | 32 | #endif -------------------------------------------------------------------------------- /src/kernels/kernels.cpp.in: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | 21 | #include "kernels.h" 22 | 23 | namespace Kernels { 24 | 25 | std::string tricubicinterpolateCL = R"CLC( 26 | @TRICUBIC_INTERPOLATE_KERNEL_STRING@ 27 | )CLC"; 28 | 29 | std::string scalarfieldCL = R"CLC( 30 | @SCALAR_FIELD_KERNEL_STRING@ 31 | )CLC"; 32 | 33 | } -------------------------------------------------------------------------------- /src/kernels/kernels.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | 21 | #ifndef KERNELS_H 22 | #define KERNELS_H 23 | 24 | #include 25 | 26 | namespace Kernels { 27 | 28 | extern std::string tricubicinterpolateCL; 29 | 30 | extern std::string scalarfieldCL; 31 | 32 | } 33 | 34 | #endif -------------------------------------------------------------------------------- /src/levelset.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef LEVELSET_H 21 | #define LEVELSET_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "vmath.h" 30 | #include "array3d.h" 31 | #include "grid3d.h" 32 | #include "interpolation.h" 33 | #include "collision.h" 34 | #include "trianglemesh.h" 35 | #include "macvelocityfield.h" 36 | #include "gridindexvector.h" 37 | #include "fluidsimassert.h" 38 | 39 | class LevelSet 40 | { 41 | public: 42 | LevelSet(); 43 | LevelSet(int i, int j, int k, double dx); 44 | ~LevelSet(); 45 | 46 | void setSurfaceMesh(TriangleMesh mesh); 47 | void calculateSignedDistanceField(); 48 | void calculateSignedDistanceField(int numLayers); 49 | void calculateSurfaceCurvature(); 50 | double getSurfaceCurvature(vmath::vec3 p); 51 | double getSurfaceCurvature(vmath::vec3 p, vmath::vec3 *normal); 52 | double getSurfaceCurvature(unsigned int tidx); 53 | Array3d getSignedDistanceField() { return _signedDistance; } 54 | vmath::vec3 getClosestPointOnSurface(vmath::vec3 p); 55 | vmath::vec3 getClosestPointOnSurface(vmath::vec3 p, int *tidx); 56 | double getDistance(vmath::vec3 p); 57 | double getSignedDistance(vmath::vec3 p); 58 | double getDistance(GridIndex g); 59 | double getSignedDistance(GridIndex g); 60 | bool isPointInInsideCell(vmath::vec3 p); 61 | 62 | private: 63 | void _resetSignedDistanceField(); 64 | void _calculateUnsignedSurfaceDistanceSquared(); 65 | void _calculateDistancesSquaredForTriangle(int triangleIndex); 66 | void _getTriangleGridCellOverlap(Triangle t, GridIndexVector &cells); 67 | void _calculateUnsignedDistanceSquared(); 68 | void _getCellLayers(std::vector &layers); 69 | void _getNeighbourGridIndices6(GridIndex g, GridIndex n[6]); 70 | void _getLayerCells(int idx, GridIndexVector &layer, 71 | GridIndexVector &nextLayer, 72 | Array3d &layerGrid); 73 | void _calculateUnsignedDistanceSquaredForLayer(GridIndexVector &q); 74 | void _setLevelSetCell(GridIndex g, double dist, int tidx); 75 | void _resetLevelSetCell(GridIndex g); 76 | void _squareRootDistanceField(); 77 | void _calculateDistanceFieldSigns(); 78 | void _updateCellSign(GridIndex g, std::vector &triangleCenters, 79 | std::vector &triangleDirections); 80 | void _floodFillMissingSignedDistances(); 81 | void _floodFillWithDistance(GridIndex g, double val); 82 | 83 | vmath::vec3 _findClosestPointOnSurface(GridIndex g); 84 | vmath::vec3 _findClosestPointOnSurface(vmath::vec3 p); 85 | vmath::vec3 _findClosestPointOnSurface(vmath::vec3 p, int *tidx); 86 | vmath::vec3 _evaluateVelocityAtPosition(MACVelocityField &vgrid, vmath::vec3 p); 87 | vmath::vec3 _evaluateVelocityAtGridIndex(MACVelocityField &vgrid, GridIndex g); 88 | double _minDistToTriangleSquared(vmath::vec3 p, int tidx); 89 | double _minDistToTriangleSquared(GridIndex g, int tidx); 90 | double _minDistToTriangleSquared(vmath::vec3 p, int tidx, vmath::vec3 *point); 91 | 92 | double _calculateCurvatureAtVertex(int idx); 93 | void _getCurvatureSamplePoints(int vidx, std::vector &points, 94 | std::vector &tris); 95 | void _getTrianglePatch(int vertexIndex, double *area, std::vector &tris); 96 | int _getRandomTriangle(std::vector &tris, std::vector &distribution); 97 | vmath::vec3 _getRandomPointInTriangle(int tidx); 98 | 99 | double _linearInterpolateSignedDistance(vmath::vec3 p); 100 | double _cubicInterpolateSignedDistance(vmath::vec3 p); 101 | 102 | bool _isPointInsideSurface(vmath::vec3 p); 103 | bool _isCellInsideSurface(GridIndex g); 104 | bool _isCellInsideSurface(int i, int j, int k); 105 | 106 | int _isize = 0; 107 | int _jsize = 0; 108 | int _ksize = 0; 109 | double _dx = 0.0; 110 | int _numLayers; 111 | 112 | TriangleMesh _surfaceMesh; 113 | 114 | Array3d _signedDistance; 115 | Array3d _indexGrid; 116 | Array3d _isDistanceSet; 117 | 118 | std::vector _vertexCurvatures; 119 | double _surfaceCurvatureSampleRadius = 6.0; // radius in # of cells 120 | int _maxSurfaceCurvatureSamples = 40; 121 | Array3d _triangleHash; 122 | 123 | }; 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /src/logfile.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "logfile.h" 21 | 22 | LogFile::LogFile() : _path("logs"), 23 | _filename(getTime() + ".txt"), 24 | _startTimeString(getTime()), 25 | _separator("------------------------------------------------------------") { 26 | } 27 | 28 | LogFile::LogFile(std::string filename) : _path("logs"), 29 | _filename(filename), 30 | _startTimeString(getTime()), 31 | _separator("------------------------------------------------------------") { 32 | } 33 | 34 | LogFile::LogFile(std::string filename, std::string extension) : 35 | _path("logs"), 36 | _filename(filename + "." + extension), 37 | _startTimeString(getTime()), 38 | _separator("------------------------------------------------------------") { 39 | } 40 | 41 | LogFile::~LogFile() { 42 | } 43 | 44 | void LogFile::setPath(std::string path) { 45 | _path = path; 46 | } 47 | 48 | void LogFile::setSeparator(std::string sep) { 49 | _separator = sep; 50 | } 51 | 52 | void LogFile::enableConsole() { 53 | _isWritingToConsole = true; 54 | } 55 | 56 | void LogFile::disableConsole() { 57 | _isWritingToConsole = false; 58 | } 59 | 60 | std::string LogFile::getString() { 61 | return _stream.str(); 62 | } 63 | 64 | void LogFile::clear() { 65 | _stream.str(std::string()); 66 | } 67 | 68 | void LogFile::newline() { 69 | _stream << std::endl; 70 | _print("\n"); 71 | _write(); 72 | } 73 | 74 | void LogFile::separator() { 75 | _stream << _separator << std::endl; 76 | _print(_separator + "\n"); 77 | _write(); 78 | } 79 | 80 | void LogFile::timestamp() { 81 | std::string time = getTime(); 82 | _stream << time << std::endl; 83 | _print(time + "\n"); 84 | _write(); 85 | } 86 | 87 | void LogFile::log(std::ostream &s) { 88 | std::ostringstream &out = dynamic_cast(s); 89 | _stream << out.str(); 90 | _print(out.str()); 91 | _write(); 92 | } 93 | 94 | void LogFile::log(std::string str, int indentLevel) { 95 | log(str, "", indentLevel); 96 | } 97 | 98 | void LogFile::log(std::string str, int value, int indentLevel) { 99 | std::ostringstream v; 100 | v << value; 101 | log(str, v.str(), indentLevel); 102 | } 103 | 104 | void LogFile::log(std::string str, double value, int precision, int indentLevel) { 105 | double scale = (double)pow(10, precision); 106 | std::ostringstream v; 107 | v << floor(value*scale) / (scale); 108 | log(str, v.str(), indentLevel); 109 | } 110 | 111 | void LogFile::log(std::string str, std::string value, int indentLevel) { 112 | std::ostringstream out; 113 | for (int i = 0; i < indentLevel; i++) { 114 | out << "\t"; 115 | } 116 | 117 | out << str << value << std::endl; 118 | _stream << out.str(); 119 | _print(out.str()); 120 | _write(); 121 | } 122 | 123 | std::string LogFile::getTime() { 124 | time_t rawtime; 125 | struct tm * timeinfo; 126 | char buffer[80]; 127 | 128 | time (&rawtime); 129 | timeinfo = localtime(&rawtime); 130 | strftime(buffer, 80, "%d-%b-%Y %Hh%Mm%Ss\0", timeinfo); 131 | 132 | return std::string(buffer); 133 | } 134 | 135 | void LogFile::print(std::string str) { 136 | _print(str); 137 | } 138 | 139 | void LogFile::_print(std::string str) { 140 | if (_isWritingToConsole) { 141 | std::cout << str; 142 | std::cout.flush(); 143 | } 144 | } 145 | 146 | void LogFile::_write() { 147 | std::ofstream out; 148 | out.open(_path + "/" + _filename, std::ios::out | std::ios::app); 149 | 150 | out << _stream.str(); 151 | out.close(); 152 | clear(); 153 | } -------------------------------------------------------------------------------- /src/logfile.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | 21 | #ifndef LOGFILE_H 22 | #define LOGFILE_H 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "stopwatch.h" 32 | 33 | class LogFile 34 | { 35 | public: 36 | LogFile(); 37 | LogFile(std::string filename); 38 | LogFile(std::string filename, std::string extension); 39 | ~LogFile(); 40 | 41 | LogFile(LogFile &obj) { 42 | _path = obj._path; 43 | _filename = obj._filename; 44 | _startTimeString = obj._startTimeString; 45 | _separator = obj._separator; 46 | } 47 | 48 | LogFile operator=(LogFile &rhs) 49 | { 50 | _path = rhs._path; 51 | _filename = rhs._filename; 52 | _startTimeString = rhs._startTimeString; 53 | _separator = rhs._separator; 54 | 55 | return *this; 56 | } 57 | 58 | void setPath(std::string path); 59 | void setSeparator(std::string separator); 60 | void enableConsole(); 61 | void disableConsole(); 62 | std::string getString(); 63 | void clear(); 64 | void newline(); 65 | void separator(); 66 | void timestamp(); 67 | void log(std::ostream &out); 68 | void log(std::string str, int indentLevel = 0); 69 | void log(std::string str, int value, int indentLevel = 0); 70 | void log(std::string str, double value, int precision = 0, int indentLevel = 0); 71 | void log(std::string str, std::string value = "", int indentLevel = 0); 72 | std::string getTime(); 73 | std::string getSrartTimeString() { return _startTimeString; } 74 | void print(std::string str); 75 | 76 | private: 77 | void _print(std::string str); 78 | void _write(); 79 | 80 | std::string _path; 81 | std::string _filename; 82 | std::string _startTimeString; 83 | std::string _separator; 84 | std::ostringstream _stream; 85 | bool _isWritingToConsole = true; 86 | }; 87 | 88 | #endif -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | 3 | int main() { 4 | 5 | // This example will drop a ball of fluid in the center 6 | // of the fluid simulation domain. 7 | 8 | int isize = 64; 9 | int jsize = 64; 10 | int ksize = 64; 11 | double dx = 0.125; 12 | FluidSimulation fluidsim(isize, jsize, ksize, dx); 13 | 14 | fluidsim.setSurfaceSubdivisionLevel(2); 15 | 16 | double x, y, z; 17 | fluidsim.getSimulationDimensions(&x, &y, &z); 18 | fluidsim.addImplicitFluidPoint(x/2, y/2, z/2, 7.0); 19 | 20 | fluidsim.addBodyForce(0.0, -25.0, 0.0); 21 | fluidsim.initialize(); 22 | 23 | double timestep = 1.0 / 30.0; 24 | for (;;) { 25 | fluidsim.update(timestep); 26 | } 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /src/main.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "fluidsimulation.h" -------------------------------------------------------------------------------- /src/markerparticle.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef MARKERPARTICLE_H 21 | #define MARKERPARTICLE_H 22 | 23 | #include "vmath.h" 24 | 25 | struct MarkerParticle { 26 | vmath::vec3 position; 27 | vmath::vec3 velocity; 28 | 29 | MarkerParticle() {} 30 | 31 | MarkerParticle(vmath::vec3 p) : position(p) {} 32 | MarkerParticle(vmath::vec3 p, vmath::vec3 v) : 33 | position(p), 34 | velocity(v) {} 35 | 36 | MarkerParticle(double x, double y, double z) : 37 | position(x, y, z) {} 38 | }; 39 | 40 | #endif -------------------------------------------------------------------------------- /src/polygonizer3d.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef POLYGONIZER3D_H 21 | #define POLYGONIZER3D_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "scalarfield.h" 31 | #include "array3d.h" 32 | #include "grid3d.h" 33 | #include "trianglemesh.h" 34 | #include "vmath.h" 35 | #include "gridindexvector.h" 36 | #include "stopwatch.h" 37 | #include "fluidsimassert.h" 38 | 39 | class Polygonizer3d 40 | { 41 | public: 42 | Polygonizer3d(); 43 | Polygonizer3d(ScalarField *scalarField); 44 | 45 | ~Polygonizer3d(); 46 | 47 | void setSurfaceCellMask(Array3d *mask); 48 | TriangleMesh polygonizeSurface(); 49 | 50 | private: 51 | struct EdgeGrid { 52 | Array3d U; // store index to vertex 53 | Array3d V; 54 | Array3d W; 55 | 56 | EdgeGrid() : U(Array3d(0, 0, 0)), 57 | V(Array3d(0, 0, 0)), 58 | W(Array3d(0, 0, 0)) {} 59 | 60 | EdgeGrid(int i, int j, int k) : 61 | U(Array3d(i, j + 1, k + 1, -1)), 62 | V(Array3d(i + 1, j, k + 1, -1)), 63 | W(Array3d(i + 1, j + 1, k, -1)) {} 64 | }; 65 | 66 | vmath::vec3 _getVertexPosition(GridIndex v); 67 | double _getVertexFieldValue(GridIndex v); 68 | bool _isCellOnSurface(GridIndex g); 69 | void _polygonizeCell(GridIndex g, EdgeGrid &edges, TriangleMesh &mesh); 70 | int _calculateCubeIndex(GridIndex g); 71 | void _calculateVertexList(GridIndex g, 72 | int cubeIndex, 73 | EdgeGrid &edges, 74 | std::vector &meshVertices, 75 | int vertList[12]); 76 | vmath::vec3 _vertexInterp(vmath::vec3 p1, vmath::vec3 p2, double valp1, double valp2); 77 | void _calculateSurfaceTriangles(GridIndexVector &surfaceCells, TriangleMesh &mesh); 78 | void _findSurfaceCells(GridIndexVector &surfaceCells); 79 | 80 | static const int _edgeTable[256]; 81 | static const int _triTable[256][16]; 82 | 83 | int _isize = 0; 84 | int _jsize = 0; 85 | int _ksize = 0; 86 | double _dx = 0.0; 87 | 88 | double _surfaceThreshold = 0.5; 89 | 90 | ScalarField *_scalarField; 91 | bool _isScalarFieldSet = false; 92 | 93 | Array3d *_surfaceCellMask; 94 | bool _isSurfaceCellMaskSet = false; 95 | 96 | }; 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /src/pressuresolver.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef PRESSURESOLVER_H 21 | #define PRESSURESOLVER_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "macvelocityfield.h" 30 | #include "gridindexkeymap.h" 31 | #include "logfile.h" 32 | #include "grid3d.h" 33 | #include "array3d.h" 34 | #include "fluidmaterialgrid.h" 35 | #include "gridindexvector.h" 36 | #include "fluidsimassert.h" 37 | 38 | struct PressureSolverParameters { 39 | double cellwidth; 40 | double density; 41 | double deltaTime; 42 | 43 | GridIndexVector *fluidCells; 44 | FluidMaterialGrid *materialGrid; 45 | MACVelocityField *velocityField; 46 | LogFile *logfile; 47 | }; 48 | 49 | /******************************************************************************** 50 | VectorXd 51 | ********************************************************************************/ 52 | 53 | class VectorXd 54 | { 55 | public: 56 | VectorXd(); 57 | VectorXd(int size); 58 | VectorXd(int size, double fill); 59 | VectorXd(VectorXd &vector); 60 | ~VectorXd(); 61 | 62 | const double operator [](int i) const; 63 | double& operator[](int i); 64 | 65 | inline size_t size() { 66 | return _vector.size(); 67 | } 68 | 69 | void fill(double fill); 70 | double dot(VectorXd &vector); 71 | double absMaxCoeff(); 72 | 73 | std::vector _vector; 74 | 75 | }; 76 | 77 | /******************************************************************************** 78 | MatrixCoefficients 79 | ********************************************************************************/ 80 | 81 | struct MatrixCell { 82 | char diag; 83 | char plusi; 84 | char plusj; 85 | char plusk; 86 | 87 | MatrixCell() : diag(0x00), plusi(0x00), plusj(0x00), plusk(0x00) {} 88 | }; 89 | 90 | class MatrixCoefficients 91 | { 92 | public: 93 | MatrixCoefficients(); 94 | MatrixCoefficients(int size); 95 | ~MatrixCoefficients(); 96 | 97 | const MatrixCell operator [](int i) const; 98 | MatrixCell& operator [](int i); 99 | 100 | inline size_t size() { 101 | return cells.size(); 102 | } 103 | 104 | std::vector cells; 105 | }; 106 | 107 | /******************************************************************************** 108 | PressureSolver 109 | ********************************************************************************/ 110 | 111 | class PressureSolver 112 | { 113 | public: 114 | PressureSolver(); 115 | ~PressureSolver(); 116 | 117 | void solve(PressureSolverParameters params, VectorXd &pressure); 118 | 119 | private: 120 | 121 | inline int _GridToVectorIndex(GridIndex g) { 122 | return _keymap.find(g); 123 | } 124 | inline int _GridToVectorIndex(int i, int j, int k) { 125 | return _keymap.find(i, j, k); 126 | } 127 | inline GridIndex _VectorToGridIndex(int i) { 128 | return _fluidCells->at(i); 129 | } 130 | 131 | void _initialize(PressureSolverParameters params); 132 | void _initializeGridIndexKeyMap(); 133 | void _calculateNegativeDivergenceVector(VectorXd &b); 134 | void _calculateMatrixCoefficients(MatrixCoefficients &A); 135 | int _getNumFluidOrAirCellNeighbours(int i, int j, int k); 136 | void _calculatePreconditionerVector(MatrixCoefficients &A, VectorXd &precon); 137 | void _solvePressureSystem(MatrixCoefficients &A, 138 | VectorXd &b, 139 | VectorXd &precon, 140 | VectorXd &pressure); 141 | void _applyPreconditioner(MatrixCoefficients &A, 142 | VectorXd &precon, 143 | VectorXd &residual, 144 | VectorXd &vect); 145 | void _applyMatrix(MatrixCoefficients &A, VectorXd &x, VectorXd &result); 146 | void _addScaledVector(VectorXd &v1, VectorXd &v2, double scale); 147 | void _addScaledVectors(VectorXd &v1, double s1, 148 | VectorXd &v2, double s2, 149 | VectorXd &result); 150 | 151 | int _isize = 0; 152 | int _jsize = 0; 153 | int _ksize = 0; 154 | double _dx = 0; 155 | double _density = 0; 156 | double _deltaTime = 0; 157 | int _matSize = 0; 158 | 159 | double _pressureSolveTolerance = 1e-6; 160 | int _maxCGIterations = 200; 161 | 162 | GridIndexVector *_fluidCells; 163 | FluidMaterialGrid *_materialGrid; 164 | MACVelocityField *_vField; 165 | LogFile *_logfile; 166 | GridIndexKeyMap _keymap; 167 | 168 | }; 169 | 170 | #endif -------------------------------------------------------------------------------- /src/pyfluid/__init__.py: -------------------------------------------------------------------------------- 1 | from .aabb import AABB, AABB_t 2 | from .fluidsimulation import FluidSimulation, MarkerParticle_t, DiffuseParticle_t 3 | from .fluidsimulationsavestate import FluidSimulationSaveState 4 | from .fluidsource import CuboidFluidSource, SphericalFluidSource 5 | from .gridindex import GridIndex, GridIndex_t 6 | from .vector3 import Vector3, Vector3_t 7 | from .pyfluid import load_library, unload_library -------------------------------------------------------------------------------- /src/pyfluid/array3d.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | import array 3 | from gridindex import GridIndex 4 | import method_decorators as decorators 5 | 6 | class Array3d: 7 | __metaclass__ = ABCMeta 8 | 9 | def __init__(self, isize, jsize, ksize): 10 | self.width, self.height, self.depth = isize, jsize, ksize 11 | self._num_elements = isize*jsize*ksize 12 | 13 | @abstractmethod 14 | def _init_grid(self, data): 15 | pass 16 | 17 | def fill(self, value): 18 | for i in range(self._num_elements): 19 | self._grid[i] = value 20 | 21 | @decorators.ijk_or_gridindex 22 | def __call__(self, i, j, k): 23 | if not self._is_index_in_range(i, j, k) and self._out_of_range_value != None: 24 | return self._out_of_range_value 25 | return self._grid[self._get_flat_index(i, j, k)] 26 | 27 | def __iter__(self): 28 | i = j = k = 0 29 | for v in self._grid: 30 | yield i, j, k, v 31 | i += 1 32 | if i >= self.width: 33 | i = 0 34 | j += 1 35 | if j >= self.height: 36 | j = 0 37 | k += 1 38 | 39 | @decorators.ijk_or_gridindex 40 | def get(self, i, j, k): 41 | return self(i, j, k) 42 | 43 | @decorators.ijk_or_gridindex_and_value 44 | def set(self, i, j, k, value): 45 | self._grid[self._get_flat_index(i, j, k)] = value 46 | 47 | @decorators.ijk_or_gridindex_and_value 48 | def add(self, i, j, k, value): 49 | self._grid[self._get_flat_index(i, j, k)] += value 50 | 51 | def get_num_elements(self): 52 | return self._num_elements 53 | 54 | def set_out_of_range_value(self, value = None): 55 | self._out_of_range_value = value 56 | 57 | def get_out_of_range_value(self): 58 | return self._out_of_range_value 59 | 60 | def _is_index_in_range(self, i, j, k): 61 | return (i >= 0 and j >= 0 and k >= 0 and 62 | i < self.width and j < self.height and k < self.depth) 63 | 64 | def _get_flat_index(self, i, j, k): 65 | return i + self.width*(j + self.height*k) 66 | 67 | 68 | class Array3di(Array3d): 69 | def __init__(self, isize, jsize, ksize, default_value = int()): 70 | Array3d.__init__(self, isize, jsize, ksize) 71 | self._init_grid(default_value) 72 | 73 | def _init_grid(self, default_value): 74 | self._grid = array.array('i', [default_value]*self.get_num_elements()) 75 | 76 | class Array3df(Array3d): 77 | def __init__(self, isize, jsize, ksize, default_value = float()): 78 | Array3d.__init__(self, isize, jsize, ksize) 79 | self._init_grid(default_value) 80 | 81 | def _init_grid(self, default_value): 82 | self._grid = array.array('f', [default_value]*self.get_num_elements()) 83 | 84 | class Array3dd(Array3d): 85 | def __init__(self, isize, jsize, ksize, default_value = float()): 86 | Array3d.__init__(self, isize, jsize, ksize) 87 | self._init_grid(default_value) 88 | 89 | def _init_grid(self, default_value): 90 | self._grid = array.array('d', [default_value]*self.get_num_elements()) -------------------------------------------------------------------------------- /src/pyfluid/config.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | import os 3 | 4 | from .pyfluid import pyfluid as lib 5 | from . import pybindings as pb 6 | 7 | def get_executable_directory(): 8 | return _get_directory(lib.Config_get_executable_directory) 9 | 10 | def get_output_directory(): 11 | return _get_directory(lib.Config_get_output_directory) 12 | 13 | def get_bakefiles_directory(): 14 | return _get_directory(lib.Config_get_bakefiles_directory) 15 | 16 | def get_logs_directory(): 17 | return _get_directory(lib.Config_get_logs_directory) 18 | 19 | def get_savestates_directory(): 20 | return _get_directory(lib.Config_get_savestates_directory) 21 | 22 | def get_temp_directory(): 23 | return _get_directory(lib.Config_get_temp_directory) 24 | 25 | def _get_directory(libfunc): 26 | directory = (ctypes.c_char * 4096)() 27 | pb.init_lib_func(libfunc, [ctypes.c_char_p], None) 28 | libfunc(directory) 29 | return directory.value 30 | 31 | def set_output_directory(directory): 32 | _set_directory(lib.Config_set_output_directory, directory) 33 | 34 | def set_bakefiles_directory(directory): 35 | _set_directory(lib.Config_set_bakefiles_directory, directory) 36 | 37 | def set_logs_directory(directory): 38 | _set_directory(lib.Config_set_logs_directory, directory) 39 | 40 | def set_savestates_directory(directory): 41 | _set_directory(lib.Config_set_savestates_directory, directory) 42 | 43 | def set_temp_directory(directory): 44 | _set_directory(lib.Config_set_temp_directory, directory) 45 | 46 | def _set_directory(libfunc, directory): 47 | directory = os.path.abspath(directory) 48 | if not os.path.exists(directory): 49 | os.makedirs(directory) 50 | 51 | cdir = ctypes.c_char_p(directory.encode('utf-8')) 52 | pb.init_lib_func(libfunc, [ctypes.c_char_p], None) 53 | libfunc(cdir) -------------------------------------------------------------------------------- /src/pyfluid/gridindex.py: -------------------------------------------------------------------------------- 1 | import array 2 | import ctypes 3 | 4 | class GridIndex_t(ctypes.Structure): 5 | _fields_ = [("i", ctypes.c_int), 6 | ("j", ctypes.c_int), 7 | ("k", ctypes.c_int)] 8 | 9 | class GridIndex(object): 10 | 11 | def __init__(self, i = 0, j = 0, k = 0): 12 | if isinstance(i, GridIndex): 13 | self._values = array.array('i', [i.i, i.j, i.k]) 14 | else: 15 | self._values = array.array('i', [i, j, k]) 16 | 17 | def __str__(self): 18 | return str(self.i) + " " + str(self.j) + " " + str(self.k) 19 | 20 | def __getitem__(self, key): 21 | if key < 0 or key > 2: 22 | raise IndexError("Index must be in range [0, 2]") 23 | if not isinstance(key, int): 24 | raise TypeError("Index must be an integer") 25 | 26 | return self._values[key] 27 | 28 | def __setitem__(self, key, value): 29 | if key < 0 or key > 2: 30 | raise IndexError("Index must be in range [0, 2]") 31 | if not isinstance(key, int): 32 | raise TypeError("Index must be an integer") 33 | 34 | self._values[key] = value 35 | 36 | def __iter__(self): 37 | yield self._values[0] 38 | yield self._values[1] 39 | yield self._values[2] 40 | 41 | @property 42 | def i(self): 43 | return self._values[0] 44 | 45 | @property 46 | def j(self): 47 | return self._values[1] 48 | 49 | @property 50 | def k(self): 51 | return self._values[2] 52 | 53 | @i.setter 54 | def i(self, value): 55 | self._values[0] = value 56 | 57 | @j.setter 58 | def j(self, value): 59 | self._values[1] = value 60 | 61 | @k.setter 62 | def k(self, value): 63 | self._values[2] = value 64 | -------------------------------------------------------------------------------- /src/pyfluid/method_decorators.py: -------------------------------------------------------------------------------- 1 | import numbers 2 | 3 | from .fluidsimulationsavestate import FluidSimulationSaveState 4 | from .vector3 import Vector3 5 | from .gridindex import GridIndex 6 | 7 | def ijk_or_gridindex(func): 8 | def ijk_or_gridindex_wrapper(self, *args): 9 | try: 10 | i, j, k = args 11 | except: 12 | i, j, k = args[0] 13 | return func(self, i, j, k) 14 | return ijk_or_gridindex_wrapper 15 | 16 | def ijk_or_gridindex_and_value(func): 17 | def ijk_or_gridindex_and_value_wrapper(self, *args): 18 | try: 19 | return func(self, *args) 20 | except: 21 | i, j, k = args[0] 22 | return func(self, i, j, k, args[1]) 23 | return ijk_or_gridindex_and_value_wrapper 24 | 25 | def xyz_or_vector(func): 26 | def xyz_or_vector_wrapper(self, *args): 27 | try: 28 | return func(self, *args) 29 | except: 30 | return func(self, *args[0]) 31 | return xyz_or_vector_wrapper 32 | 33 | def xyz_or_vector_and_radius(func): 34 | def xyz_or_vector_wrapper(self, *args): 35 | try: 36 | return func(self, *args) 37 | except: 38 | x, y, z = args[0] 39 | return func(self, x, y, z, args[1]) 40 | return xyz_or_vector_wrapper 41 | 42 | def check_gt_zero(func): 43 | def check_values(self, *args): 44 | for arg in args: 45 | if isinstance(arg, numbers.Real) and arg <= 0: 46 | raise ValueError("Value must be greater than zero") 47 | return func(self, *args) 48 | return check_values 49 | 50 | def check_ge_zero(func): 51 | def check_values(self, *args): 52 | for arg in args: 53 | if isinstance(arg, numbers.Real) and arg < 0: 54 | raise ValueError("Value must be greater than or equal to zero") 55 | return func(self, *args) 56 | return check_values 57 | 58 | def check_gt(value): 59 | def check_gt_decorator(func): 60 | def check_gt_wrapper(self, *args): 61 | for arg in args: 62 | if isinstance(arg, numbers.Real) and arg <= value: 63 | raise ValueError("Value must be greater than " + str(value)) 64 | return func(self, *args) 65 | return check_gt_wrapper 66 | return check_gt_decorator 67 | 68 | def check_ge(value): 69 | def check_ge_decorator(func): 70 | def check_ge_wrapper(self, *args): 71 | for arg in args: 72 | if isinstance(arg, numbers.Real) and arg < value: 73 | raise ValueError("Value must be greater than or equal to " + str(value)) 74 | return func(self, *args) 75 | return check_ge_wrapper 76 | return check_ge_decorator 77 | 78 | def check_type(argtype): 79 | def check_type_decorator(func): 80 | def check_type_wrapper(self, *args): 81 | for arg in args: 82 | if not isinstance(arg, argtype): 83 | raise TypeError("Argument must be of type " + str(argtype)) 84 | return func(self, *args) 85 | return check_type_wrapper 86 | return check_type_decorator -------------------------------------------------------------------------------- /src/pyfluid/pybindings.py: -------------------------------------------------------------------------------- 1 | from .pyfluid import pyfluid as lib 2 | from ctypes import c_char_p, c_int, byref 3 | 4 | def check_success(success, errprefix): 5 | libfunc = lib.CBindings_get_error_message 6 | init_lib_func(libfunc, [], c_char_p) 7 | if not success: 8 | raise RuntimeError(errprefix + libfunc()) 9 | 10 | def init_lib_func(libfunc, argtypes, restype): 11 | if libfunc.argtypes is None: 12 | libfunc.argtypes = argtypes 13 | libfunc.restype = restype 14 | 15 | def execute_lib_func(libfunc, params): 16 | args = [] 17 | for idx, arg in enumerate(params): 18 | try: 19 | cval = libfunc.argtypes[idx](arg) 20 | except: 21 | cval = arg 22 | args.append(cval) 23 | success = c_int(); 24 | args.append(byref(success)) 25 | 26 | result = None 27 | if libfunc.restype: 28 | funcresult = libfunc(*args) 29 | try: 30 | return libfunc.restype(funcresult).value 31 | except: 32 | return funcresult 33 | else: 34 | libfunc(*args) 35 | 36 | check_success(success, libfunc.__name__ + " - ") 37 | return result -------------------------------------------------------------------------------- /src/pyfluid/pyfluid.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | import glob 3 | import os 4 | 5 | class LibraryLoadError(Exception): 6 | def __init__(self, value): 7 | self.value = value 8 | def __str__(self): 9 | return repr(self.value) 10 | 11 | def __load_library(name): 12 | libdir = os.path.dirname(__file__) 13 | if libdir == "": 14 | libdir = "./" 15 | files = glob.glob(libdir + "/lib/*" + name + "*") 16 | 17 | library = None 18 | for f in files: 19 | try: 20 | library = ctypes.cdll.LoadLibrary(f) 21 | break 22 | except: 23 | continue 24 | 25 | if not library: 26 | raise LibraryLoadError("Unable to load library: " + name) 27 | 28 | return library 29 | 30 | def load_library(): 31 | try: 32 | global pyfluid 33 | pyfluid = __load_library("pyfluid") 34 | except: 35 | pass 36 | 37 | def unload_library(): 38 | try: 39 | global pyfluid 40 | ctypes.windll.kernel32.FreeLibrary(pyfluid._handle) 41 | except: 42 | pass 43 | 44 | 45 | pyfluid = __load_library("pyfluid") -------------------------------------------------------------------------------- /src/pyfluid/utils.py: -------------------------------------------------------------------------------- 1 | import ctypes 2 | from ctypes import c_void_p, c_char_p, c_char, c_int, c_float, c_double, byref 3 | 4 | from .pyfluid import pyfluid as lib 5 | from .gridindex import GridIndex_t 6 | from . import pybindings as pb 7 | 8 | def get_triangle_mesh_cells(mesh, dx): 9 | mesh_struct = mesh.to_struct() 10 | 11 | libfunc = lib.utils_get_triangle_mesh_cells_storage_size 12 | pb.init_lib_func(libfunc, [c_void_p, c_double, c_void_p], c_int) 13 | storage_size = pb.execute_lib_func(libfunc, [byref(mesh_struct), dx]) 14 | 15 | indices = (GridIndex_t * storage_size)() 16 | num_cells = c_int() 17 | 18 | libfunc = lib.utils_get_triangle_mesh_cells 19 | args = [c_void_p, c_double, c_void_p, c_int, c_void_p, c_void_p] 20 | pb.init_lib_func(libfunc, args, None) 21 | pb.execute_lib_func( 22 | libfunc, [byref(mesh_struct), dx, indices, storage_size, byref(num_cells)] 23 | ) 24 | 25 | output = [] 26 | for i in range(num_cells.value): 27 | output.append(indices[i]) 28 | 29 | return output 30 | 31 | 32 | def get_triangle_mesh_cells_subd2(mesh, dx): 33 | mesh_struct = mesh.to_struct() 34 | 35 | libfunc = lib.utils_get_triangle_mesh_cells_storage_size 36 | pb.init_lib_func(libfunc, [c_void_p, c_double, c_void_p], c_int) 37 | storage_size = pb.execute_lib_func(libfunc, [byref(mesh_struct), dx]) 38 | 39 | indices = (GridIndex_t * storage_size)() 40 | cell_masks = (c_char * storage_size)() 41 | num_cells = c_int() 42 | 43 | libfunc = lib.utils_get_triangle_mesh_cells_subd2 44 | args = [c_void_p, c_double, c_void_p, c_char_p, c_int, c_void_p, c_void_p] 45 | pb.init_lib_func(libfunc, args, None) 46 | 47 | params = [byref(mesh_struct), dx, indices, cell_masks, storage_size, byref(num_cells)] 48 | pb.execute_lib_func(libfunc, params) 49 | 50 | output = [] 51 | output_masks = [] 52 | for i in range(num_cells.value): 53 | output.append(indices[i]) 54 | output_masks.append(ord(cell_masks[i])) 55 | 56 | return output, output_masks -------------------------------------------------------------------------------- /src/render/blender_scripts/brick_texture_lookup_shader.osl: -------------------------------------------------------------------------------- 1 | /* 2 | This shader is used for looking up 'LEGO' brick colour data for 3 | brick positions generated by the PIC/FLIP Fluid Simulation 4 | program's (https://github.com/rlguy/GridFluidSim3D) 'LEGO' brick 5 | surface reconstruction feature. 6 | 7 | This shader is meant to be plugged into a Blender Cycles script node 8 | to convert global position to texture coordinate. 9 | */ 10 | 11 | int get_flat_index3d(int i, int j, int k, int width, int height) { 12 | return i + width * (j + height * k); 13 | } 14 | 15 | vector get_unflattened_index2d(int flatidx, int width) { 16 | int i = flatidx % width; 17 | int j = (int)floor((float)flatidx / (float)width); 18 | 19 | return vector(i, j, 0); 20 | } 21 | 22 | vector position_to_brick_index(vector pos, float bw, float bh, float bd) { 23 | return vector(floor(pos[0] / bw), floor(pos[1] / bh), floor(pos[2] / bd)); 24 | } 25 | 26 | vector rotate_about_x(vector pos, float rads) { 27 | float x = pos[0]; 28 | float y = pos[1]*cos(rads) - pos[2]*sin(rads); 29 | float z = pos[1]*sin(rads) + pos[2]*cos(rads); 30 | return vector(x, y, z); 31 | } 32 | 33 | vector rotate_about_y(vector pos, float rads) { 34 | float x = pos[2]*sin(rads) + pos[0]*cos(rads); 35 | float y = pos[1]; 36 | float z = pos[2]*cos(rads) - pos[0]*sin(rads); 37 | return vector(x, y, z); 38 | } 39 | 40 | vector rotate_about_z(vector pos, float rads) { 41 | float x = pos[0]*cos(rads) - pos[1]*sin(rads); 42 | float y = pos[0]*sin(rads) + pos[1]*cos(rads); 43 | float z = pos[2]; 44 | return vector(x, y, z); 45 | } 46 | 47 | /* 48 | model_width - Width of the model bounds in the x direction 49 | model_height - Height of the model bounds in the y direction 50 | model_depth - Depth the model bounds in the z direction 51 | 52 | brick_width - Width of the brick in the x direction 53 | brick_height - Height of the brick in the y direction 54 | brick_depth - Depth the brick in the z direction 55 | 56 | texture_width - Width of the texture image in pixels 57 | texture_height - Height of the texture image in pixels 58 | 59 | global_position - 3D Global position input to the shader 60 | out_uv - 2D texture coordinate output of the shader 61 | */ 62 | shader simple_material( 63 | float model_width = 1.0, 64 | float model_height = 1.0, 65 | float model_depth = 1.0, 66 | float brick_width = 1.0, 67 | float brick_height = 1.0, 68 | float brick_depth = 1.0, 69 | int texture_width = 1, 70 | int texture_height = 1, 71 | vector global_position = vector(0.5, 0.5, 0.5), 72 | output vector out_uv = vector(0.0, 0.0, 0.0) 73 | ) 74 | { 75 | 76 | // The fluid simulation program uses the convention that the 'up' direction is the 77 | // positive y direction. Blender uses the convention that positive z is the 'up' direction. 78 | // When the LEGO brick meshes are loaded into Blender, they are first rotated about the x-axis 79 | // by 90 degrees and then rotated about the z-axis by 90 degrees in order to face the right direction. 80 | // The global position must be rotated back so that the position matches the original position before 81 | // the mesh was rotated. 82 | // 83 | // Rotate global_position by -90 degrees about z axis and then by -90 degrees about x axis. 84 | float PI = 3.1415926535897; 85 | vector orig_position = rotate_about_z(global_position, -0.5*PI); 86 | orig_position = rotate_about_x(orig_position, -0.5*PI); 87 | 88 | int bi = (int)ceil(model_width / brick_width); 89 | int bj = (int)ceil(model_height / brick_height); 90 | int bk = (int)ceil(model_depth / brick_depth); 91 | 92 | vector brick_index = position_to_brick_index(orig_position, brick_width, brick_height, brick_depth); 93 | int flat_index = get_flat_index3d((int)brick_index[0], (int)brick_index[1], (int)brick_index[2], bi, bj); 94 | 95 | vector tex_index = get_unflattened_index2d(flat_index, texture_width); 96 | float texu = ((float)tex_index[0] + 0.5) / (float)texture_width; 97 | float texv = ((float)tex_index[1] + 0.5) / (float)texture_height; 98 | 99 | out_uv = vector(texu, texv, 0.0); 100 | } 101 | -------------------------------------------------------------------------------- /src/render/blender_scripts/import_animation-basic.py: -------------------------------------------------------------------------------- 1 | """ 2 | This script will import and render a sequence of .ply triangle meshes generated by 3 | the PIC/FLIP Fluid Simulation program (https://github.com/rlguy/GridFluidSim3D) 4 | in Blender using the Blender Python API. 5 | 6 | The triangle mesh sequence must be in the form: 7 | prefix000000.ply, prefix000001.ply, prefix000002.ply, ... 8 | """ 9 | 10 | import bpy 11 | import math 12 | 13 | # Change this variable to point towards your bakefiles directory 14 | WATER_FILEPATH_DIRECTORY = "C:\\cygwin64\\home\\Ryan\\fluidsim\\bakefiles\\" 15 | 16 | # Prefix of the mesh filename 17 | # 18 | # Example: if filename is anisotropic000000.ply, the variable would be 19 | # WATER_FILE_NAME_PREFIX = "anisotropic" 20 | # 21 | # Leave empty if there is no prefix to the file number 22 | WATER_FILE_NAME_PREFIX = "" 23 | 24 | # replace 'Water' with name of the material you would like to apply to 25 | # the imported meshes. If the material is not found, the mesh will be 26 | # rendered with the default diffuse material 27 | WATER_MATERIAL = bpy.data.materials.get('Water') 28 | 29 | # Don't change this variable, global is only used by the script 30 | WATER_MESH_OBJECT_NAME = "" 31 | 32 | def remove_mesh_from_memory(object_name): 33 | mesh = bpy.data.meshes[object_name] 34 | mesh.user_clear() 35 | bpy.data.meshes.remove(mesh) 36 | 37 | def run_before_frame_change(scene): 38 | bpy.ops.object.select_all(action='DESELECT') 39 | 40 | if not (WATER_MESH_OBJECT_NAME == ""): 41 | obj = bpy.data.objects[WATER_MESH_OBJECT_NAME] 42 | bpy.data.scenes[0].objects.unlink(obj) 43 | bpy.data.objects.remove(obj) 44 | remove_mesh_from_memory(WATER_MESH_OBJECT_NAME) 45 | 46 | def get_frame_string(framenum): 47 | lenframe = len(framenum) 48 | 49 | framestr = "" 50 | if lenframe == 1: 51 | framestr = "00000" + framenum 52 | if lenframe == 2: 53 | framestr = "0000" + framenum 54 | if lenframe == 3: 55 | framestr = "000" + framenum 56 | 57 | return framestr 58 | 59 | def smooth_mesh(mesh): 60 | for p in mesh.data.polygons: 61 | p.use_smooth = True 62 | 63 | def run_after_frame_change(scene): 64 | scene.cycles.seed = bpy.data.scenes["Scene"].frame_current 65 | 66 | cframe = str(bpy.data.scenes["Scene"].frame_current) 67 | cframe = get_frame_string(cframe) 68 | 69 | mesh_filename = WATER_FILEPATH_DIRECTORY + WATER_FILE_NAME_PREFIX + cframe + ".ply" 70 | bpy.ops.import_mesh.ply(filepath=mesh_filename) 71 | 72 | global WATER_MESH_OBJECT_NAME 73 | WATER_MESH_OBJECT_NAME = WATER_FILE_NAME_PREFIX + cframe 74 | 75 | mesh = bpy.data.objects[WATER_MESH_OBJECT_NAME] 76 | mesh.rotation_euler = (0.5*math.pi, 0, 0.5*math.pi) 77 | mesh.data.materials.append(WATER_MATERIAL) 78 | mesh.draw_type = "WIRE" 79 | smooth_mesh(mesh) 80 | 81 | bpy.ops.object.select_all(action='DESELECT') 82 | print("FINISHED LOADING FRAME: ", cframe) 83 | 84 | # Handlers 85 | bpy.app.handlers.frame_change_pre.append(run_before_frame_change) 86 | bpy.app.handlers.frame_change_post.append(run_after_frame_change) -------------------------------------------------------------------------------- /src/render/blender_scripts/import_animation-brick.py: -------------------------------------------------------------------------------- 1 | """ 2 | This script will import and render a sequence of .ply brick location 3 | meshes generated by generated by the PIC/FLIP Fluid Simulation 4 | program's (https://github.com/rlguy/GridFluidSim3D) 'LEGO' brick surface 5 | reconstruction feature. 6 | 7 | Bricks can be coloured by using the Cycles script node with the 8 | brick_texture_lookup_shader.osl shader and a colour lookup texture 9 | image generated by the brick_texture_packer program. 10 | 11 | The brick mesh sequence must be in the form: 12 | prefix000000.ply, prefix000001.ply, prefix000002.ply, ... 13 | """ 14 | 15 | import bpy 16 | import math 17 | 18 | # Change this variable to point towards your bakefiles directory 19 | BRICK_FILEPATH_DIRECTORY = "C:\\cygwin64\\home\\Ryan\\fluidsim\\bakefiles\\" 20 | 21 | # Prefix of the mesh filename 22 | # 23 | # Example: if filename is brick000000.ply, the variable would be 24 | # BRICK_FILE_NAME_PREFIX = "brick" 25 | # 26 | # Leave empty if there is no prefix to the file number 27 | BRICK_FILE_NAME_PREFIX = "brick" 28 | 29 | # Name of the Blender scene object that will be duplicated over each 30 | # brick position 31 | BRICK_MODEL_OBJECT_NAME = "legobrick" 32 | 33 | # Don't change this variable, global is only used by the script 34 | BRICK_MESH_OBJECT_NAME = "" 35 | 36 | def remove_mesh_from_memory(object_name): 37 | mesh = bpy.data.meshes[object_name] 38 | mesh.user_clear() 39 | bpy.data.meshes.remove(mesh) 40 | 41 | def run_before_frame_change(scene): 42 | bpy.ops.object.select_all(action='DESELECT') 43 | 44 | if not (BRICK_MESH_OBJECT_NAME == ""): 45 | obj = bpy.data.objects[BRICK_MESH_OBJECT_NAME] 46 | bpy.data.scenes[0].objects.unlink(obj) 47 | bpy.data.objects.remove(obj) 48 | remove_mesh_from_memory(BRICK_MESH_OBJECT_NAME) 49 | 50 | def get_frame_string(framenum): 51 | lenframe = len(framenum) 52 | 53 | framestr = "" 54 | if lenframe == 1: 55 | framestr = "00000" + framenum 56 | if lenframe == 2: 57 | framestr = "0000" + framenum 58 | if lenframe == 3: 59 | framestr = "000" + framenum 60 | 61 | return framestr 62 | 63 | def run_after_frame_change(scene): 64 | scene.cycles.seed = bpy.data.scenes["Scene"].frame_current 65 | 66 | cframe = str(bpy.data.scenes["Scene"].frame_current) 67 | cframe = get_frame_string(cframe) 68 | 69 | mesh_filename = BRICK_FILEPATH_DIRECTORY + BRICK_FILE_NAME_PREFIX + cframe + ".ply" 70 | bpy.ops.import_mesh.ply(filepath=mesh_filename) 71 | 72 | global BRICK_MESH_OBJECT_NAME 73 | BRICK_MESH_OBJECT_NAME = BRICK_FILE_NAME_PREFIX + cframe 74 | mesh = bpy.data.objects[BRICK_MESH_OBJECT_NAME] 75 | mesh.rotation_euler = (0.5*math.pi, 0, 0.5*math.pi) 76 | 77 | parent = mesh 78 | child = bpy.data.objects[BRICK_MODEL_OBJECT_NAME] 79 | child.parent = parent 80 | parent.dupli_type = 'VERTS' 81 | 82 | bpy.ops.object.select_all(action='DESELECT') 83 | print("FINISHED LOADING FRAME: ", cframe) 84 | 85 | #Frame Change / Saving Function Triggers 86 | bpy.app.handlers.frame_change_pre.append(run_before_frame_change) 87 | bpy.app.handlers.frame_change_post.append(run_after_frame_change) 88 | -------------------------------------------------------------------------------- /src/render/blender_scripts/import_animation-diffuse.py: -------------------------------------------------------------------------------- 1 | """ 2 | This script will import and render a sequence of .ply triangle meshes and a 3 | sequence of diffuse particle meshes generated by the PIC/FLIP Fluid Simulation 4 | program (https://github.com/rlguy/GridFluidSim3D) in Blender using the Blender 5 | Python API. 6 | 7 | The triangle mesh sequence and diffuse mesh sequence must be in the form: 8 | prefix000000.ply, prefix000001.ply, prefix000002.ply, ... 9 | """ 10 | 11 | import bpy 12 | import math 13 | 14 | # Change this variable to point towards your bakefiles directory 15 | MESH_FILEPATH_DIRECTORY = "C:\\cygwin64\\home\\Ryan\\fluidsim\\bakefiles\\" 16 | 17 | # Prefix of the mesh filename 18 | # 19 | # Example: if filename is anisotropic000000.ply, the variable would be 20 | # WATER_FILE_NAME_PREFIX = "anisotropic" 21 | # 22 | # Leave empty if there is no prefix to the file number 23 | WATER_FILE_NAME_PREFIX = "" 24 | 25 | # Prefix of the diffuse mesh filename 26 | DIFFUSE_FILE_NAME_PREFIX = "diffuse" 27 | 28 | # Name of the Blender scene object that will be duplicated over each 29 | # diffuse particle position 30 | DIFFUSE_PARTICLE_OBJECT_NAME = 'particle' 31 | 32 | # replace 'Water' or 'DiffuseParticle' with name of the material you would 33 | # like to apply to the imported meshes. If the material is not found, the 34 | # mesh will be rendered with the default diffuse material 35 | WATER_MATERIAL = bpy.data.materials.get('Water') 36 | DIFFUSE_MATERIAL = bpy.data.materials.get('DiffuseParticle') 37 | 38 | # Don't change these variables, globals are only used by the script 39 | WATER_MESH_OBJECT_NAME = "Water Object" 40 | DIFFUSE_MESH_OBJECT_NAME = "Diffuse Object" 41 | 42 | def remove_mesh_from_memory(object_name): 43 | mesh = bpy.data.meshes[object_name] 44 | mesh.user_clear() 45 | bpy.data.meshes.remove(mesh) 46 | 47 | def run_before_frame_change(scene): 48 | bpy.ops.object.select_all(action='DESELECT') 49 | 50 | if not (WATER_MESH_OBJECT_NAME == "Water Object"): 51 | obj = bpy.data.objects[WATER_MESH_OBJECT_NAME] 52 | bpy.data.scenes[0].objects.unlink(obj) 53 | bpy.data.objects.remove(obj) 54 | remove_mesh_from_memory(WATER_MESH_OBJECT_NAME) 55 | 56 | if not (DIFFUSE_MESH_OBJECT_NAME == "Diffuse Object"): 57 | obj = bpy.data.objects[DIFFUSE_MESH_OBJECT_NAME] 58 | bpy.data.scenes[0].objects.unlink(obj) 59 | bpy.data.objects.remove(obj) 60 | remove_mesh_from_memory(DIFFUSE_MESH_OBJECT_NAME) 61 | 62 | def get_frame_string(framenum): 63 | lenframe = len(framenum) 64 | 65 | framestr = "" 66 | if lenframe == 1: 67 | framestr = "00000" + framenum 68 | if lenframe == 2: 69 | framestr = "0000" + framenum 70 | if lenframe == 3: 71 | framestr = "000" + framenum 72 | 73 | return framestr 74 | 75 | def smooth_mesh(mesh): 76 | for p in mesh.data.polygons: 77 | p.use_smooth = True 78 | 79 | def run_after_frame_change(scene): 80 | scene.cycles.seed = bpy.data.scenes["Scene"].frame_current 81 | 82 | cframe = str(bpy.data.scenes["Scene"].frame_current) 83 | cframe = get_frame_string(cframe) 84 | 85 | # Import Diffuse Particle Mesh 86 | diffuse_mesh_filename = MESH_FILEPATH_DIRECTORY + DIFFUSE_FILE_NAME_PREFIX + cframe + ".ply" 87 | bpy.ops.import_mesh.ply(filepath=diffuse_mesh_filename) 88 | 89 | global DIFFUSE_MESH_OBJECT_NAME 90 | DIFFUSE_MESH_OBJECT_NAME = DIFFUSE_FILE_NAME_PREFIX + cframe 91 | diffuse_mesh = bpy.data.objects[DIFFUSE_MESH_OBJECT_NAME] 92 | diffuse_mesh.data.materials.append(DIFFUSE_MATERIAL) 93 | diffuse_mesh.rotation_euler = (0.5*math.pi, 0, 0.5*math.pi) 94 | diffuse_mesh.draw_type = "BOUNDS" 95 | 96 | parent = diffuse_mesh 97 | child = bpy.data.objects[DIFFUSE_PARTICLE_OBJECT_NAME] 98 | child.parent = parent 99 | parent.dupli_type = 'VERTS' 100 | 101 | bpy.ops.object.select_all(action='DESELECT') 102 | 103 | # Import Water Mesh 104 | water_mesh_filename = MESH_FILEPATH_DIRECTORY + WATER_FILE_NAME_PREFIX + cframe + ".ply" 105 | bpy.ops.import_mesh.ply(filepath=water_mesh_filename) 106 | 107 | global WATER_MESH_OBJECT_NAME 108 | WATER_MESH_OBJECT_NAME = WATER_FILE_NAME_PREFIX + cframe 109 | water_mesh = bpy.data.objects[WATER_MESH_OBJECT_NAME] 110 | water_mesh.data.materials.append(WATER_MATERIAL) 111 | water_mesh.rotation_euler = (0.5*math.pi, 0, 0.5*math.pi) 112 | water_mesh.draw_type = "WIRE" 113 | smooth_mesh(water_mesh) 114 | 115 | bpy.ops.object.select_all(action='DESELECT') 116 | print("FINISHED LOADING FRAME: ", cframe) 117 | 118 | # Handlers 119 | bpy.app.handlers.frame_change_pre.append(run_before_frame_change) 120 | bpy.app.handlers.frame_change_post.append(run_after_frame_change) 121 | -------------------------------------------------------------------------------- /src/render/blender_scripts/import_animation-diffuse_particles_only.py: -------------------------------------------------------------------------------- 1 | """ 2 | This script will import and render a sequence of .ply diffuse particle meshes 3 | generated by the PIC/FLIP Fluid Simulation program (https://github.com/rlguy/GridFluidSim3D) 4 | in Blender using the Blender Python API. 5 | 6 | The diffuse mesh sequence must be in the form: 7 | prefix000000.ply, prefix000001.ply, prefix000002.ply, ... 8 | """ 9 | 10 | import bpy 11 | import math 12 | 13 | # Change this variable to point towards your bakefiles directory 14 | MESH_FILEPATH_DIRECTORY = "C:\\cygwin64\\home\\Ryan\\fluidsim\\bakefiles\\" 15 | 16 | # Prefix of the mesh filename 17 | # 18 | # Example: if filename is diffuse000000.ply, the variable would be 19 | # DIFFUSE_FILE_NAME_PREFIX = "diffuse" 20 | # 21 | # Leave empty if there is no prefix to the file number 22 | DIFFUSE_FILE_NAME_PREFIX = "diffuse" 23 | 24 | # Name of the Blender scene object that will be duplicated over each 25 | # diffuse particle position 26 | DIFFUSE_PARTICLE_OBJECT_NAME = 'particle' 27 | 28 | # replace 'Water' or 'DiffuseParticle' with name of the material you would 29 | # like to apply to the imported meshes. If the material is not found, the 30 | # mesh will be rendered with the default diffuse material 31 | DIFFUSE_MATERIAL = bpy.data.materials.get('DiffuseParticle') 32 | 33 | # Don't change these variables, globals are only used by the script 34 | DIFFUSE_MESH_OBJECT_NAME = "Diffuse Object" 35 | 36 | def remove_mesh_from_memory(object_name): 37 | mesh = bpy.data.meshes[object_name] 38 | mesh.user_clear() 39 | bpy.data.meshes.remove(mesh) 40 | 41 | def run_before_frame_change(scene): 42 | bpy.ops.object.select_all(action='DESELECT') 43 | 44 | if not (DIFFUSE_MESH_OBJECT_NAME == "Diffuse Object"): 45 | obj = bpy.data.objects[DIFFUSE_MESH_OBJECT_NAME] 46 | bpy.data.scenes[0].objects.unlink(obj) 47 | bpy.data.objects.remove(obj) 48 | remove_mesh_from_memory(DIFFUSE_MESH_OBJECT_NAME) 49 | 50 | def get_frame_string(framenum): 51 | lenframe = len(framenum) 52 | 53 | framestr = "" 54 | if lenframe == 1: 55 | framestr = "00000" + framenum 56 | if lenframe == 2: 57 | framestr = "0000" + framenum 58 | if lenframe == 3: 59 | framestr = "000" + framenum 60 | 61 | return framestr 62 | 63 | def smooth_mesh(mesh): 64 | for p in mesh.data.polygons: 65 | p.use_smooth = True 66 | 67 | def run_after_frame_change(scene): 68 | scene.cycles.seed = bpy.data.scenes["Scene"].frame_current 69 | 70 | cframe = str(bpy.data.scenes["Scene"].frame_current) 71 | cframe = get_frame_string(cframe) 72 | 73 | # Import Diffuse Particle Mesh 74 | diffuse_mesh_filename = MESH_FILEPATH_DIRECTORY + DIFFUSE_FILE_NAME_PREFIX + cframe + ".ply" 75 | bpy.ops.import_mesh.ply(filepath=diffuse_mesh_filename) 76 | 77 | global DIFFUSE_MESH_OBJECT_NAME 78 | DIFFUSE_MESH_OBJECT_NAME = DIFFUSE_FILE_NAME_PREFIX + cframe 79 | diffuse_mesh = bpy.data.objects[DIFFUSE_MESH_OBJECT_NAME] 80 | diffuse_mesh.data.materials.append(DIFFUSE_MATERIAL) 81 | diffuse_mesh.rotation_euler = (0.5*math.pi, 0, 0.5*math.pi) 82 | diffuse_mesh.draw_type = "BOUNDS" 83 | 84 | parent = diffuse_mesh 85 | child = bpy.data.objects[DIFFUSE_PARTICLE_OBJECT_NAME] 86 | child.parent = parent 87 | parent.dupli_type = 'VERTS' 88 | 89 | bpy.ops.object.select_all(action='DESELECT') 90 | print("FINISHED LOADING FRAME: ", cframe) 91 | 92 | # Handlers 93 | bpy.app.handlers.frame_change_pre.append(run_before_frame_change) 94 | bpy.app.handlers.frame_change_post.append(run_after_frame_change) 95 | -------------------------------------------------------------------------------- /src/render/brick_texture_packer/README.md: -------------------------------------------------------------------------------- 1 | This program packs a sequence of numbered LEGO brick texture data files into a sequence of PNG images. 2 | 3 | LEGO brick texture data files are generated by the [PIC/FLIP Fluid Simulation program](https://github.com/rlguy/GridFluidSim3D) when LEGO brick data output is enabled. Each data file contains colour data as a list of unsigned chars, each corresponding to a LEGO brick. This program will convert this data into a PNG image which can then be used in a shader to look up brick colours. 4 | 5 | Compiling with g++: 6 | 7 | g++ lodepng/lodepng.cpp brick_texture_packer.cpp -ansi -pedantic -Wall -O3 -o brick_texture_packer 8 | 9 | Usage: 10 | 11 | ./brick_texture_packer --start_number [first_frame_number] --input [input_format_string] --output [output_format_string] 12 | 13 | Example usage: 14 | 15 | ./brick_texture_packer --start_number 30 --input bricktexture%06d.data --output texture%04d.png 16 | 17 | The above invocation will process a sequence of data files starting at frame 30 18 | 19 | bricktexture000030.data 20 | bricktexture000031.data 21 | bricktexture000032.data 22 | bricktexture000033.data 23 | bricktexture000034.data 24 | bricktexture000035.data 25 | bricktexture000036.data 26 | . 27 | . 28 | . 29 | 30 | into a sequence of PNG files 31 | 32 | texture0030.png 33 | texture0031.png 34 | texture0032.png 35 | texture0033.png 36 | texture0034.png 37 | texture0035.png 38 | texture0036.png 39 | . 40 | . 41 | . 42 | -------------------------------------------------------------------------------- /src/render/brick_texture_packer/lodepng/README.md: -------------------------------------------------------------------------------- 1 | LodePNG 2 | ------- 3 | 4 | PNG encoder and decoder in C and C++. 5 | 6 | Home page: http://lodev.org/lodepng/ 7 | 8 | Only two files are needed to allow your program to read and write PNG files: lodepng.cpp and lodepng.h. 9 | 10 | The other files in the project are just examples, unit tests, etc... 11 | -------------------------------------------------------------------------------- /src/scalarfield.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef IMPLICITSURFACESCALARFIELD_H 21 | #define IMPLICITSURFACESCALARFIELD_H 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "vmath.h" 28 | #include "array3d.h" 29 | #include "grid3d.h" 30 | #include "interpolation.h" 31 | #include "aabb.h" 32 | #include "fluidmaterialgrid.h" 33 | #include "fluidsimassert.h" 34 | 35 | class ScalarField 36 | { 37 | public: 38 | ScalarField(); 39 | ScalarField(int i, int j, int k, double dx); 40 | ~ScalarField(); 41 | 42 | void getGridDimensions(int *i, int *j, int *k) { *i = _isize; *j = _jsize; *k = _ksize; } 43 | double getCellSize() { return _dx; } 44 | 45 | void clear(); 46 | void setPointRadius(double r); 47 | double getPointRadius(); 48 | void setSurfaceThreshold(double t); 49 | double getSurfaceThreshold(); 50 | void setMaxScalarFieldThreshold(double t); 51 | void setMaxScalarFieldThreshold(); 52 | double getMaxScalarFieldThreshold(); 53 | bool isMaxScalarFieldThresholdSet(); 54 | void enableWeightField(); 55 | bool isWeightFieldEnabled(); 56 | void applyWeightField(); 57 | void addPoint(vmath::vec3 pos, double radius); 58 | void addPoint(vmath::vec3 pos); 59 | void addPointValue(vmath::vec3 pos, double radius, double value); 60 | void addPointValue(vmath::vec3 pos, double value); 61 | void addCuboid(vmath::vec3 pos, double w, double h, double d); 62 | void addEllipsoid(vmath::vec3 p, vmath::mat3 G, double r); 63 | void addEllipsoid(vmath::vec3 p, vmath::mat3 G); 64 | void addEllipsoidValue(vmath::vec3 p, vmath::mat3 G, double r, double value); 65 | void addEllipsoidValue(vmath::vec3 p, vmath::mat3 G, double value); 66 | void setMaterialGrid(FluidMaterialGrid &matGrid); 67 | void setMaterialGrid(GridIndexVector &solidCells); 68 | void setSolidCells(GridIndexVector &solidCells); 69 | void getScalarField(Array3d &field); 70 | double getScalarFieldValue(GridIndex g); 71 | double getScalarFieldValue(int i, int j, int k); 72 | double getScalarFieldValueAtCellCenter(GridIndex g); 73 | double getScalarFieldValueAtCellCenter(int i, int j, int k); 74 | void getSetScalarFieldValues(Array3d &field); 75 | bool isScalarFieldValueSet(GridIndex g); 76 | bool isScalarFieldValueSet(int i, int j, int k); 77 | double getRawScalarFieldValue(GridIndex g); 78 | double getRawScalarFieldValue(int i, int j, int k); 79 | bool isCellInsideSurface(int i, int j, int k); 80 | double getWeight(int i, int j, int k); 81 | double getWeight(GridIndex g); 82 | void getWeightField(Array3d &field); 83 | void setScalarFieldValue(int i, int j, int k, double value); 84 | void setScalarFieldValue(GridIndex g, double value); 85 | void setCellFieldValues(int i, int j, int k, double value); 86 | void setCellFieldValues(GridIndex g, double value); 87 | void addScalarFieldValue(int i, int j, int k, double value); 88 | void addScalarFieldValue(GridIndex g, double value); 89 | void addCellFieldValues(int i, int j, int k, double value); 90 | void addCellFieldValues(GridIndex g, double value); 91 | double tricubicInterpolation(vmath::vec3 p); 92 | void setOffset(vmath::vec3 offset); 93 | vmath::vec3 getOffset(); 94 | bool isPointInside(vmath::vec3 p); 95 | 96 | Array3d* getPointerToScalarField(); 97 | Array3d* getPointerToWeightField(); 98 | 99 | private: 100 | 101 | double _evaluateTricubicFieldFunctionForRadiusSquared(double rsq); 102 | 103 | int _isize = 0; 104 | int _jsize = 0; 105 | int _ksize = 0; 106 | double _dx = 0.0; 107 | 108 | double _radius = 0.0; 109 | double _invRadius = 1.0; 110 | double _coef1 = 0.0; 111 | double _coef2 = 0.0; 112 | double _coef3 = 0.0; 113 | 114 | double _surfaceThreshold = 0.5; 115 | double _maxScalarFieldThreshold = 0.0; 116 | bool _isMaxScalarFieldThresholdSet = false; 117 | 118 | Array3d _field; 119 | Array3d _isVertexSolid; 120 | Array3d _weightField; 121 | Array3d _isVertexSet; 122 | 123 | bool _isWeightFieldEnabled = false; 124 | 125 | vmath::vec3 _gridOffset; 126 | }; 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /src/sphericalfluidsource.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "sphericalfluidsource.h" 21 | 22 | SphericalFluidSource::SphericalFluidSource() { 23 | } 24 | 25 | SphericalFluidSource::SphericalFluidSource(vmath::vec3 pos, double r) : 26 | FluidSource(), 27 | _position(pos), 28 | _radius(r > 0.0 ? r : 0.0) { 29 | } 30 | 31 | SphericalFluidSource::SphericalFluidSource(vmath::vec3 pos, double r, vmath::vec3 velocity) : 32 | FluidSource(velocity), 33 | _position(pos), 34 | _radius(r > 0.0 ? r : 0.0) { 35 | } 36 | 37 | SphericalFluidSource::~SphericalFluidSource() { 38 | } 39 | 40 | vmath::vec3 SphericalFluidSource::getPosition() { 41 | return _position; 42 | } 43 | 44 | void SphericalFluidSource::setPosition(vmath::vec3 pos) { 45 | _position = pos; 46 | } 47 | 48 | AABB SphericalFluidSource::getAABB() { 49 | double d = 2.0*_radius; 50 | vmath::vec3 p = _position - vmath::vec3(_radius, _radius, _radius); 51 | return AABB(p, d, d, d); 52 | } 53 | 54 | bool SphericalFluidSource::containsPoint(vmath::vec3 p) { 55 | vmath::vec3 v = p - getPosition(); 56 | double lensq = vmath::lengthsq(v); 57 | return lensq < _radius*_radius; 58 | } 59 | 60 | double SphericalFluidSource::getRadius() { 61 | return _radius; 62 | } 63 | 64 | void SphericalFluidSource::setRadius(double r) { 65 | if (r < 0.0) { 66 | r = 0.0; 67 | } 68 | _radius = r; 69 | } 70 | 71 | void SphericalFluidSource::setCenter(vmath::vec3 p) { 72 | _position = p; 73 | } 74 | 75 | void SphericalFluidSource::expand(double val) { 76 | _radius += 0.5 * val; 77 | 78 | if (_radius < 0.0) { 79 | _radius = 0.0; 80 | } 81 | } 82 | 83 | void SphericalFluidSource::_getOverlappingCells(GridIndexVector &indices, double dx) { 84 | int isize = indices.width; 85 | int jsize = indices.height; 86 | int ksize = indices.depth; 87 | double r = _radius; 88 | GridIndex gmin, gmax; 89 | Grid3d::getGridIndexBounds(_position, r, dx, isize, jsize, ksize, &gmin, &gmax); 90 | 91 | double rsq = r*r; 92 | double distsq; 93 | vmath::vec3 p; 94 | vmath::vec3 v; 95 | for (int k = gmin.k; k <= gmax.k; k++) { 96 | for (int j = gmin.j; j <= gmax.j; j++) { 97 | for (int i = gmin.i; i <= gmax.i; i++) { 98 | p = Grid3d::GridIndexToCellCenter(i, j, k, dx); 99 | v = p - _position; 100 | distsq = vmath::dot(v, v); 101 | if (distsq < rsq) { 102 | indices.push_back(i, j, k); 103 | } 104 | } 105 | } 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/sphericalfluidsource.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef SPHERICALFLUIDSOURCE_H 21 | #define SPHERICALFLUIDSOURCE_H 22 | 23 | #include "fluidsource.h" 24 | 25 | #include 26 | 27 | #include "vmath.h" 28 | #include "aabb.h" 29 | #include "fluidmaterialgrid.h" 30 | 31 | class SphericalFluidSource : public FluidSource 32 | { 33 | public: 34 | SphericalFluidSource(); 35 | SphericalFluidSource(vmath::vec3 pos, double r); 36 | SphericalFluidSource(vmath::vec3 pos, double r, vmath::vec3 velocity); 37 | ~SphericalFluidSource(); 38 | 39 | virtual vmath::vec3 getPosition(); 40 | virtual void setPosition(vmath::vec3 pos); 41 | virtual AABB getAABB(); 42 | virtual bool containsPoint(vmath::vec3 p); 43 | 44 | double getRadius(); 45 | void setRadius(double r); 46 | void setCenter(vmath::vec3 p); 47 | void expand(double val); 48 | 49 | private: 50 | 51 | virtual void _getOverlappingCells(GridIndexVector &storage, double dx); 52 | 53 | vmath::vec3 _position; 54 | double _radius = 0.0; 55 | 56 | }; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/stopwatch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #include "stopwatch.h" 21 | 22 | StopWatch::StopWatch() 23 | { 24 | } 25 | 26 | void StopWatch::start() { 27 | 28 | #if defined(__linux__) || defined(__APPLE__) || defined(__MACOSX) 29 | struct timeval tp; 30 | gettimeofday(&tp, nullptr); 31 | _tbegin = (double)tp.tv_sec + (double)tp.tv_usec / 1000000.0; 32 | #elif defined(_WIN32) 33 | _tbegin = (double)GetTickCount() / 1000.0; 34 | #else 35 | #endif 36 | 37 | _isStarted = true; 38 | } 39 | 40 | 41 | void StopWatch::stop() { 42 | if (!_isStarted) { 43 | return; 44 | } 45 | 46 | #if defined(__linux__) || defined(__APPLE__) || defined(__MACOSX) 47 | struct timeval tp; 48 | gettimeofday(&tp, nullptr); 49 | _tend = (double)tp.tv_sec + (double)tp.tv_usec / 1000000.0; 50 | #elif defined(_WIN32) 51 | _tend = (double)GetTickCount() / 1000.0; 52 | #else 53 | #endif 54 | 55 | double time = _tend - _tbegin; 56 | _timeRunning += time; 57 | } 58 | 59 | void StopWatch::reset() { 60 | _isStarted = false; 61 | _timeRunning = 0.0; 62 | } 63 | 64 | double StopWatch::getTime() { 65 | return _timeRunning >= 0.0 ? _timeRunning : 0.0; 66 | } -------------------------------------------------------------------------------- /src/stopwatch.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef STOPWATCH_H 21 | #define STOPWATCH_H 22 | 23 | #if defined(__linux__) || defined(__APPLE__) || defined(__MACOSX) 24 | #include 25 | #elif defined(_WIN32) 26 | #include 27 | #include 28 | #else 29 | #endif 30 | 31 | class StopWatch 32 | { 33 | public: 34 | StopWatch(); 35 | void start(); 36 | void stop(); 37 | void reset(); 38 | double getTime(); // in seconds 39 | 40 | private: 41 | bool _isStarted = false; 42 | double _tbegin, _tend; 43 | double _timeRunning = 0.0; 44 | }; 45 | 46 | #endif -------------------------------------------------------------------------------- /src/triangle.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef TRIANGLE_H 21 | #define TRIANGLE_H 22 | 23 | struct Triangle { 24 | int tri[3]; // indices to a vertex 25 | 26 | Triangle() { 27 | tri[0] = 0; 28 | tri[1] = 0; 29 | tri[2] = 0; 30 | } 31 | 32 | Triangle(int p1, int p2, int p3) { 33 | tri[0] = p1; 34 | tri[1] = p2; 35 | tri[2] = p3; 36 | } 37 | }; 38 | 39 | #endif -------------------------------------------------------------------------------- /src/turbulencefield.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef TURBULENCEFIELD_H 21 | #define TURBULENCEFIELD_H 22 | 23 | #include "array3d.h" 24 | #include "grid3d.h" 25 | #include "interpolation.h" 26 | #include "macvelocityfield.h" 27 | #include "gridindexvector.h" 28 | #include "fluidmaterialgrid.h" 29 | #include "vmath.h" 30 | #include "fluidsimassert.h" 31 | 32 | class TurbulenceField 33 | { 34 | public: 35 | TurbulenceField(); 36 | ~TurbulenceField(); 37 | 38 | void calculateTurbulenceField(MACVelocityField *vfield, 39 | GridIndexVector &fluidCells); 40 | void calculateTurbulenceField(MACVelocityField *vfield, 41 | FluidMaterialGrid &mgrid); 42 | 43 | void destroyTurbulenceField(); 44 | double evaluateTurbulenceAtPosition(vmath::vec3 p); 45 | 46 | private: 47 | 48 | void _getVelocityGrid(MACVelocityField *macfield, 49 | Array3d &vgrid); 50 | double _calculateTurbulenceAtGridCell(int i, int j, int k, 51 | Array3d &vgrid); 52 | 53 | 54 | Array3d _field; 55 | 56 | int _isize, _jsize, _ksize; 57 | double _dx; 58 | double _radius; 59 | 60 | GridIndex cellNeighbours[124]; 61 | }; 62 | 63 | #endif -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Ryan L. Guy 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgement in the product documentation would be 15 | appreciated but is not required. 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 3. This notice may not be removed or altered from any source distribution. 19 | */ 20 | #ifndef UTILS_H 21 | #define UTILS_H 22 | 23 | #include 24 | 25 | #include "trianglemesh.h" 26 | #include "array3d.h" 27 | 28 | namespace utils { 29 | typedef struct TriangleMesh_t { 30 | float *vertices; 31 | int *triangles; 32 | int numVertices; 33 | int numTriangles; 34 | } TriangleMesh_t; 35 | 36 | void structToTriangleMesh(TriangleMesh_t &mesh_data, TriangleMesh &mesh); 37 | 38 | void _getTriangleGridZ( 39 | TriangleMesh &m, double dx, Array3d > &ztrigrid); 40 | 41 | void _getTriangleCollisionsZ( 42 | vmath::vec3 origin, std::vector &indices, TriangleMesh &m, 43 | std::vector &collisions); 44 | 45 | double _randomDouble(double min, double max); 46 | 47 | void _getCollisionGridZ( 48 | TriangleMesh &m, double dx, Array3d > &zcollisions); 49 | 50 | void getCellsInsideTriangleMesh( 51 | TriangleMesh &m, int isize, int jsize, int ksize, double dx, 52 | std::vector &cells); 53 | 54 | void getCellsInsideTriangleMesh( 55 | TriangleMesh mesh, double dx, std::vector &cells); 56 | 57 | void _getCollisionGridZSubd2( 58 | TriangleMesh &m, double dx, 59 | Array3d > &zcollisions, 60 | Array3d > &zsubcollisions); 61 | 62 | bool isCellInside(double z, std::vector *zvals); 63 | 64 | bool isCellInside(int i, int j, int k, double dx, std::vector *zvals); 65 | 66 | void sortInsideBorderCells( 67 | Array3d &cellgrid, 68 | std::vector &insideCells, 69 | std::vector &borderCells); 70 | 71 | unsigned char getCellFillMask( 72 | GridIndex g, double dx, Array3d > &zsubcollisions); 73 | 74 | 75 | void getCellsInsideTriangleMeshSubd2( 76 | TriangleMesh &m, int isize, int jsize, int ksize, double dx, 77 | std::vector &cells, std::vector &cell_masks); 78 | 79 | void getCellsInsideTriangleMeshSubd2( 80 | TriangleMesh mesh, double dx, 81 | std::vector &cells, std::vector &cell_masks); 82 | 83 | } 84 | 85 | #endif --------------------------------------------------------------------------------