Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt53
-rw-r--r--build_files/cmake/Modules/FindOpenVDB.cmake74
-rw-r--r--build_files/cmake/config/blender_lite.cmake1
-rw-r--r--build_files/cmake/config/bpy_module.cmake1
-rw-r--r--build_files/cmake/macros.cmake10
-rw-r--r--intern/CMakeLists.txt4
-rw-r--r--intern/openvdb/CMakeLists.txt69
-rw-r--r--intern/openvdb/intern/openvdb_dense_convert.cc167
-rw-r--r--intern/openvdb/intern/openvdb_dense_convert.h130
-rw-r--r--intern/openvdb/intern/openvdb_reader.cc136
-rw-r--r--intern/openvdb/intern/openvdb_reader.h55
-rw-r--r--intern/openvdb/intern/openvdb_writer.cc118
-rw-r--r--intern/openvdb/intern/openvdb_writer.h57
-rw-r--r--intern/openvdb/openvdb_capi.cc240
-rw-r--r--intern/openvdb/openvdb_capi.h108
-rw-r--r--intern/openvdb/openvdb_util.cc38
-rw-r--r--intern/openvdb/openvdb_util.h57
-rw-r--r--release/scripts/modules/sys_info.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_smoke.py22
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h15
-rw-r--r--source/blender/blenkernel/CMakeLists.txt13
-rw-r--r--source/blender/blenkernel/intern/pointcache.c481
-rw-r--r--source/blender/blenkernel/intern/smoke.c11
-rw-r--r--source/blender/editors/space_view3d/drawobject.c18
-rw-r--r--source/blender/makesdna/DNA_smoke_types.h14
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt8
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c43
-rw-r--r--source/blender/python/intern/CMakeLists.txt9
-rw-r--r--source/blender/python/intern/bpy_app.c3
-rw-r--r--source/blender/python/intern/bpy_app_build_options.c7
-rw-r--r--source/blender/python/intern/bpy_app_openvdb.c117
-rw-r--r--source/blender/python/intern/bpy_app_openvdb.h38
-rw-r--r--source/blenderplayer/CMakeLists.txt4
33 files changed, 2077 insertions, 51 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e0326f1d75e..4ec5053eb58 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -242,6 +242,9 @@ option(WITH_OPENSUBDIV "Enable OpenSubdiv for surface subdivision" _init_OPEN
option(WITH_SUBSURF_WERROR "Treat warnings as errors in subsurf code" OFF)
mark_as_advanced(WITH_COMPOSITOR_WERROR)
+option(WITH_OPENVDB "Enable features relying on OpenVDB" OFF)
+option(WITH_OPENVDB_BLOSC "Enable blosc compression for OpenVDB, only enable if OpenVDB was built with blosc support" OFF)
+
# GHOST Windowing Library Options
option(WITH_GHOST_DEBUG "Enable debugging output for the GHOST library" OFF)
mark_as_advanced(WITH_GHOST_DEBUG)
@@ -677,10 +680,11 @@ if(NOT WITH_BOOST)
set_and_warn(WITH_CYCLES OFF)
set_and_warn(WITH_AUDASPACE OFF)
set_and_warn(WITH_INTERNATIONAL OFF)
+ set_and_warn(WITH_OPENVDB OFF)
set_and_warn(WITH_OPENAL OFF) # depends on AUDASPACE
set_and_warn(WITH_GAMEENGINE OFF) # depends on AUDASPACE
-elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_AUDASPACE OR WITH_INTERNATIONAL)
+elseif(WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_AUDASPACE OR WITH_INTERNATIONAL OR WITH_OPENVDB)
# Keep enabled
else()
# Enabled but we don't need it
@@ -1056,6 +1060,24 @@ if(UNIX AND NOT APPLE)
endif()
endif()
+ if(WITH_OPENVDB)
+ find_package_wrapper(OpenVDB)
+
+ set(TBB ${LIBDIR}/tbb)
+ set(TBB_LIBRARIES tbb)
+ set(TBB_LIBPATH ${TBB}/lib)
+
+ set(OPENVDB_LIBRARIES ${OPENVDB_LIBRARIES} ${BOOST_LIBRARIES} ${ZLIB_LIBRARIES} ${TBB_LIBRARIES})
+ set(OPENVDB_LIBPATH) # TODO, remove and reference the absolute path everywhere
+ set(OPENVDB_DEFINITIONS)
+
+ if(NOT OPENVDB_FOUND)
+ set(WITH_OPENVDB OFF)
+ set(WITH_OPENVDB_BLOSC OFF)
+ message(STATUS "OpenVDB not found")
+ endif()
+ endif()
+
if(WITH_BOOST)
# uses in build instructions to override include and library variables
if(NOT BOOST_CUSTOM)
@@ -1076,6 +1098,9 @@ if(UNIX AND NOT APPLE)
if(WITH_CYCLES_NETWORK)
list(APPEND __boost_packages serialization)
endif()
+ if(WITH_OPENVDB)
+ list(APPEND __boost_packages iostreams)
+ endif()
find_package(Boost 1.48 COMPONENTS ${__boost_packages})
if(NOT Boost_FOUND)
# try to find non-multithreaded if -mt not found, this flag
@@ -1561,7 +1586,14 @@ elseif(WIN32)
set(OPENCOLORIO_LIBPATH ${LIBDIR}/opencolorio/lib)
set(OPENCOLORIO_DEFINITIONS)
endif()
-
+
+ if(WITH_OPENVDB)
+ set(OPENVDB ${LIBDIR}/openvdb)
+ set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include)
+ set(OPENVDB_LIBRARIES openvdb ${TBB_LIBRARIES})
+ set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib)
+ set(OPENVDB_DEFINITIONS)
+ endif()
if(WITH_MOD_CLOTH_ELTOPO)
set(LAPACK ${LIBDIR}/lapack)
@@ -1834,6 +1866,14 @@ elseif(WIN32)
set(SDL_LIBPATH ${SDL}/lib)
endif()
+ if(WITH_OPENVDB)
+ set(OPENVDB ${LIBDIR}/openvdb)
+ set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include)
+ set(OPENVDB_LIBRARIES openvdb ${TBB_LIBRARIES})
+ set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib)
+ set(OPENVDB_DEFINITIONS)
+ endif()
+
set(PLATFORM_LINKFLAGS "-Xlinker --stack=2097152")
## DISABLE - causes linking errors
@@ -2139,6 +2179,14 @@ elseif(APPLE)
set(OPENCOLORIO_LIBPATH ${OPENCOLORIO}/lib)
endif()
+ if(WITH_OPENVDB)
+ set(OPENVDB ${LIBDIR}/openvdb)
+ set(OPENVDB_INCLUDE_DIRS ${OPENVDB}/include)
+ set(OPENVDB_LIBRARIES openvdb ${TBB_LIBRARIES})
+ set(OPENVDB_LIBPATH ${LIBDIR}/openvdb/lib)
+ set(OPENVDB_DEFINITIONS)
+ endif()
+
if(WITH_LLVM)
set(LLVM_ROOT_DIR ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation")
set(LLVM_VERSION "3.4" CACHE STRING "Version of LLVM to use")
@@ -2981,6 +3029,7 @@ if(FIRST_RUN)
info_cfg_option(WITH_CYCLES)
info_cfg_option(WITH_FREESTYLE)
info_cfg_option(WITH_OPENCOLORIO)
+ info_cfg_option(WITH_OPENVDB)
info_cfg_text("Compiler Options:")
info_cfg_option(WITH_BUILDINFO)
diff --git a/build_files/cmake/Modules/FindOpenVDB.cmake b/build_files/cmake/Modules/FindOpenVDB.cmake
new file mode 100644
index 00000000000..a13feab8e0e
--- /dev/null
+++ b/build_files/cmake/Modules/FindOpenVDB.cmake
@@ -0,0 +1,74 @@
+# - Find OPENVDB library
+# Find the native OPENVDB includes and library
+# This module defines
+# OPENVDB_INCLUDE_DIRS, where to find openvdb.h, Set when
+# OPENVDB_INCLUDE_DIR is found.
+# OPENVDB_LIBRARIES, libraries to link against to use OPENVDB.
+# OPENVDB_ROOT_DIR, The base directory to search for OPENVDB.
+# This can also be an environment variable.
+# OPENVDB_FOUND, If false, do not try to use OPENVDB.
+#
+# also defined, but not for general use are
+# OPENVDB_LIBRARY, where to find the OPENVDB library.
+
+#=============================================================================
+# Copyright 2015 Blender Foundation.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+
+# If OPENVDB_ROOT_DIR was defined in the environment, use it.
+IF(NOT OPENVDB_ROOT_DIR AND NOT $ENV{OPENVDB_ROOT_DIR} STREQUAL "")
+ SET(OPENVDB_ROOT_DIR $ENV{OPENVDB_ROOT_DIR})
+ENDIF()
+
+SET(_openvdb_SEARCH_DIRS
+ ${OPENVDB_ROOT_DIR}
+ /usr/local
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+ /opt/openvdb
+ /opt/lib/openvdb
+)
+
+FIND_PATH(OPENVDB_INCLUDE_DIR
+ NAMES
+ openvdb/openvdb.h
+ HINTS
+ ${_openvdb_SEARCH_DIRS}
+ PATH_SUFFIXES
+ include
+)
+
+FIND_LIBRARY(OPENVDB_LIBRARY
+ NAMES
+ openvdb
+ HINTS
+ ${_openvdb_SEARCH_DIRS}
+ PATH_SUFFIXES
+ lib64 lib
+)
+
+# handle the QUIETLY and REQUIRED arguments and set OPENVDB_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(OPENVDB DEFAULT_MSG
+ OPENVDB_LIBRARY OPENVDB_INCLUDE_DIR)
+
+IF(OPENVDB_FOUND)
+ SET(OPENVDB_LIBRARIES ${OPENVDB_LIBRARY})
+ SET(OPENVDB_INCLUDE_DIRS ${OPENVDB_INCLUDE_DIR})
+ENDIF(OPENVDB_FOUND)
+
+MARK_AS_ADVANCED(
+ OPENVDB_INCLUDE_DIR
+ OPENVDB_LIBRARY
+)
+
+UNSET(_openvdb_SEARCH_DIRS)
diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake
index 99e90caf793..a479506d0d7 100644
--- a/build_files/cmake/config/blender_lite.cmake
+++ b/build_files/cmake/config/blender_lite.cmake
@@ -47,6 +47,7 @@ set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLORIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENIMAGEIO OFF CACHE BOOL "" FORCE)
set(WITH_OPENMP OFF CACHE BOOL "" FORCE)
+set(WITH_OPENVDB OFF CACHE BOOL "" FORCE)
set(WITH_RAYOPTIMIZATION OFF CACHE BOOL "" FORCE)
set(WITH_SDL OFF CACHE BOOL "" FORCE)
set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/config/bpy_module.cmake b/build_files/cmake/config/bpy_module.cmake
index b5b13b40987..41140151f04 100644
--- a/build_files/cmake/config/bpy_module.cmake
+++ b/build_files/cmake/config/bpy_module.cmake
@@ -31,3 +31,4 @@ set(WITH_INPUT_NDOF OFF CACHE BOOL "" FORCE)
set(WITH_OPENCOLLADA OFF CACHE BOOL "" FORCE)
set(WITH_INTERNATIONAL OFF CACHE BOOL "" FORCE)
set(WITH_BULLET OFF CACHE BOOL "" FORCE)
+set(WITH_OPENVDB OFF CACHE BOOL "" FORCE)
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 6194bd8351c..28617cd7142 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -282,6 +282,9 @@ function(SETUP_LIBDIRS)
if(WITH_OPENCOLORIO)
link_directories(${OPENCOLORIO_LIBPATH})
endif()
+ if(WITH_OPENVDB)
+ link_directories(${OPENVDB_LIBPATH})
+ endif()
if(WITH_IMAGE_OPENJPEG AND WITH_SYSTEM_OPENJPEG)
link_directories(${OPENJPEG_LIBPATH})
endif()
@@ -400,6 +403,9 @@ function(setup_liblinks
target_link_libraries(${target} ${OPENSUBDIV_LIBRARIES})
endif()
endif()
+ if(WITH_OPENVDB)
+ target_link_libraries(${target} ${OPENVDB_LIBRARIES})
+ endif()
if(WITH_CYCLES_OSL)
target_link_libraries(${target} ${OSL_LIBRARIES})
endif()
@@ -713,6 +719,10 @@ function(SETUP_BLENDER_SORTED_LIBS)
list(APPEND BLENDER_SORTED_LIBS bf_intern_opensubdiv)
endif()
+ if(WITH_OPENVDB)
+ list(APPEND BLENDER_SORTED_LIBS bf_intern_openvdb)
+ endif()
+
foreach(SORTLIB ${BLENDER_SORTED_LIBS})
set(REMLIB ${SORTLIB})
foreach(SEARCHLIB ${BLENDER_LINK_LIBS})
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index f5f2d1c0156..43e5b6bff3e 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -82,3 +82,7 @@ endif()
if(WIN32)
add_subdirectory(utfconv)
endif()
+
+if(WITH_OPENVDB)
+ add_subdirectory(openvdb)
+endif()
diff --git a/intern/openvdb/CMakeLists.txt b/intern/openvdb/CMakeLists.txt
new file mode 100644
index 00000000000..ce683e7d319
--- /dev/null
+++ b/intern/openvdb/CMakeLists.txt
@@ -0,0 +1,69 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2015, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Kevin Dietrich.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ intern
+)
+
+set(INC_SYS
+)
+
+set(SRC
+ openvdb_capi.h
+)
+
+if(WITH_OPENVDB)
+ add_definitions(
+ -DWITH_OPENVDB
+ )
+
+ list(APPEND INC_SYS
+ ${BOOST_INCLUDE_DIR}
+ ${OPENEXR_INCLUDE_DIRS}
+ ${OPENVDB_INCLUDE_DIRS}
+ )
+
+ list(APPEND SRC
+ intern/openvdb_dense_convert.cc
+ intern/openvdb_reader.cc
+ intern/openvdb_writer.cc
+ openvdb_capi.cc
+ openvdb_util.cc
+
+ intern/openvdb_dense_convert.h
+ intern/openvdb_reader.h
+ intern/openvdb_writer.h
+ openvdb_util.h
+ )
+
+ if(WITH_OPENVDB_BLOSC)
+ add_definitions(
+ -DWITH_OPENVDB_BLOSC
+ )
+ endif()
+endif()
+
+blender_add_lib(bf_intern_openvdb "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/openvdb/intern/openvdb_dense_convert.cc b/intern/openvdb/intern/openvdb_dense_convert.cc
new file mode 100644
index 00000000000..d4f62776988
--- /dev/null
+++ b/intern/openvdb/intern/openvdb_dense_convert.cc
@@ -0,0 +1,167 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "openvdb_dense_convert.h"
+
+#include <openvdb/tools/ValueTransformer.h> /* for tools::foreach */
+
+namespace internal {
+
+openvdb::Mat4R convertMatrix(const float mat[4][4])
+{
+ return openvdb::Mat4R(
+ mat[0][0], mat[0][1], mat[0][2], mat[0][3],
+ mat[1][0], mat[1][1], mat[1][2], mat[1][3],
+ mat[2][0], mat[2][1], mat[2][2], mat[2][3],
+ mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
+}
+
+
+class MergeScalarGrids {
+ typedef openvdb::FloatTree ScalarTree;
+
+ openvdb::tree::ValueAccessor<const ScalarTree> m_acc_x, m_acc_y, m_acc_z;
+
+public:
+ MergeScalarGrids(const ScalarTree *x_tree, const ScalarTree *y_tree, const ScalarTree *z_tree)
+ : m_acc_x(*x_tree)
+ , m_acc_y(*y_tree)
+ , m_acc_z(*z_tree)
+ {}
+
+ MergeScalarGrids(const MergeScalarGrids &other)
+ : m_acc_x(other.m_acc_x)
+ , m_acc_y(other.m_acc_y)
+ , m_acc_z(other.m_acc_z)
+ {}
+
+ void operator()(const openvdb::Vec3STree::ValueOnIter &it) const
+ {
+ using namespace openvdb;
+
+ const math::Coord xyz = it.getCoord();
+ float x = m_acc_x.getValue(xyz);
+ float y = m_acc_y.getValue(xyz);
+ float z = m_acc_z.getValue(xyz);
+
+ it.setValue(math::Vec3s(x, y, z));
+ }
+};
+
+openvdb::GridBase *OpenVDB_export_vector_grid(
+ OpenVDBWriter *writer,
+ const openvdb::Name &name,
+ const float *data_x, const float *data_y, const float *data_z,
+ const int res[3],
+ float fluid_mat[4][4],
+ openvdb::VecType vec_type,
+ const bool is_color,
+ const openvdb::FloatGrid *mask)
+{
+ using namespace openvdb;
+
+ math::CoordBBox bbox(Coord(0), Coord(res[0] - 1, res[1] - 1, res[2] - 1));
+ Mat4R mat = convertMatrix(fluid_mat);
+ math::Transform::Ptr transform = math::Transform::createLinearTransform(mat);
+
+ FloatGrid::Ptr grid[3];
+
+ grid[0] = FloatGrid::create(0.0f);
+ tools::Dense<const float, tools::LayoutXYZ> dense_grid_x(bbox, data_x);
+ tools::copyFromDense(dense_grid_x, grid[0]->tree(), TOLERANCE);
+
+ grid[1] = FloatGrid::create(0.0f);
+ tools::Dense<const float, tools::LayoutXYZ> dense_grid_y(bbox, data_y);
+ tools::copyFromDense(dense_grid_y, grid[1]->tree(), TOLERANCE);
+
+ grid[2] = FloatGrid::create(0.0f);
+ tools::Dense<const float, tools::LayoutXYZ> dense_grid_z(bbox, data_z);
+ tools::copyFromDense(dense_grid_z, grid[2]->tree(), TOLERANCE);
+
+ Vec3SGrid::Ptr vecgrid = Vec3SGrid::create(Vec3s(0.0f));
+
+ /* Activate voxels in the vector grid based on the scalar grids to ensure
+ * thread safety later on */
+ for (int i = 0; i < 3; ++i) {
+ vecgrid->tree().topologyUnion(grid[i]->tree());
+ }
+
+ MergeScalarGrids op(&(grid[0]->tree()), &(grid[1]->tree()), &(grid[2]->tree()));
+ tools::foreach(vecgrid->beginValueOn(), op, true, false);
+
+ vecgrid->setTransform(transform);
+
+ if (mask) {
+ vecgrid = tools::clip(*vecgrid, *mask);
+ }
+
+ vecgrid->setName(name);
+ vecgrid->setIsInWorldSpace(false);
+ vecgrid->setVectorType(vec_type);
+ vecgrid->insertMeta("is_color", BoolMetadata(is_color));
+ vecgrid->setGridClass(GRID_STAGGERED);
+
+ writer->insert(vecgrid);
+
+ return vecgrid.get();
+}
+
+void OpenVDB_import_grid_vector(
+ OpenVDBReader *reader,
+ const openvdb::Name &name,
+ float **data_x, float **data_y, float **data_z,
+ const int res[3])
+{
+ using namespace openvdb;
+
+ if (!reader->hasGrid(name)) {
+ std::fprintf(stderr, "OpenVDB grid %s not found in file!\n", name.c_str());
+ memset(*data_x, 0, sizeof(float) * res[0] * res[1] * res[2]);
+ memset(*data_y, 0, sizeof(float) * res[0] * res[1] * res[2]);
+ memset(*data_z, 0, sizeof(float) * res[0] * res[1] * res[2]);
+ return;
+ }
+
+ Vec3SGrid::Ptr vgrid = gridPtrCast<Vec3SGrid>(reader->getGrid(name));
+ Vec3SGrid::ConstAccessor acc = vgrid->getConstAccessor();
+ math::Coord xyz;
+ int &x = xyz[0], &y = xyz[1], &z = xyz[2];
+
+ size_t index = 0;
+ for (z = 0; z < res[2]; ++z) {
+ for (y = 0; y < res[1]; ++y) {
+ for (x = 0; x < res[0]; ++x, ++index) {
+ math::Vec3s value = acc.getValue(xyz);
+ (*data_x)[index] = value.x();
+ (*data_y)[index] = value.y();
+ (*data_z)[index] = value.z();
+ }
+ }
+ }
+}
+
+} /* namespace internal */
diff --git a/intern/openvdb/intern/openvdb_dense_convert.h b/intern/openvdb/intern/openvdb_dense_convert.h
new file mode 100644
index 00000000000..fd10334c4ad
--- /dev/null
+++ b/intern/openvdb/intern/openvdb_dense_convert.h
@@ -0,0 +1,130 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __OPENVDB_DENSE_CONVERT_H__
+#define __OPENVDB_DENSE_CONVERT_H__
+
+#include "openvdb_reader.h"
+#include "openvdb_writer.h"
+
+#include <openvdb/tools/Clip.h>
+#include <openvdb/tools/Dense.h>
+
+#include <cstdio>
+
+#define TOLERANCE 1e-3f
+
+namespace internal {
+
+openvdb::Mat4R convertMatrix(const float mat[4][4]);
+
+template <typename GridType, typename T>
+GridType *OpenVDB_export_grid(
+ OpenVDBWriter *writer,
+ const openvdb::Name &name,
+ const T *data,
+ const int res[3],
+ float fluid_mat[4][4],
+ const openvdb::FloatGrid *mask)
+{
+ using namespace openvdb;
+
+ math::CoordBBox bbox(Coord(0), Coord(res[0] - 1, res[1] - 1, res[2] - 1));
+ Mat4R mat = convertMatrix(fluid_mat);
+ math::Transform::Ptr transform = math::Transform::createLinearTransform(mat);
+
+ typename GridType::Ptr grid = GridType::create(T(0));
+
+ tools::Dense<const T, openvdb::tools::LayoutXYZ> dense_grid(bbox, data);
+ tools::copyFromDense(dense_grid, grid->tree(), (T)TOLERANCE);
+
+ grid->setTransform(transform);
+
+ if (mask) {
+ grid = tools::clip(*grid, *mask);
+ }
+
+ grid->setName(name);
+ grid->setIsInWorldSpace(false);
+ grid->setVectorType(openvdb::VEC_INVARIANT);
+
+ writer->insert(grid);
+
+ return grid.get();
+}
+
+template <typename GridType, typename T>
+void OpenVDB_import_grid(
+ OpenVDBReader *reader,
+ const openvdb::Name &name,
+ T **data,
+ const int res[3])
+{
+ using namespace openvdb;
+
+ if (!reader->hasGrid(name)) {
+ std::fprintf(stderr, "OpenVDB grid %s not found in file!\n", name.c_str());
+ memset(*data, 0, sizeof(T) * res[0] * res[1] * res[2]);
+ return;
+ }
+
+ typename GridType::Ptr grid = gridPtrCast<GridType>(reader->getGrid(name));
+ typename GridType::ConstAccessor acc = grid->getConstAccessor();
+
+ math::Coord xyz;
+ int &x = xyz[0], &y = xyz[1], &z = xyz[2];
+
+ size_t index = 0;
+ for (z = 0; z < res[2]; ++z) {
+ for (y = 0; y < res[1]; ++y) {
+ for (x = 0; x < res[0]; ++x, ++index) {
+ (*data)[index] = acc.getValue(xyz);
+ }
+ }
+ }
+}
+
+openvdb::GridBase *OpenVDB_export_vector_grid(
+ OpenVDBWriter *writer,
+ const openvdb::Name &name,
+ const float *data_x, const float *data_y, const float *data_z,
+ const int res[3],
+ float fluid_mat[4][4],
+ openvdb::VecType vec_type,
+ const bool is_color,
+ const openvdb::FloatGrid *mask);
+
+
+void OpenVDB_import_grid_vector(
+ OpenVDBReader *reader,
+ const openvdb::Name &name,
+ float **data_x, float **data_y, float **data_z,
+ const int res[3]);
+
+} /* namespace internal */
+
+#endif /* __OPENVDB_DENSE_CONVERT_H__ */
diff --git a/intern/openvdb/intern/openvdb_reader.cc b/intern/openvdb/intern/openvdb_reader.cc
new file mode 100644
index 00000000000..8b15b81710d
--- /dev/null
+++ b/intern/openvdb/intern/openvdb_reader.cc
@@ -0,0 +1,136 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "openvdb_reader.h"
+#include "openvdb_util.h"
+
+OpenVDBReader::OpenVDBReader()
+ : m_meta_map(new openvdb::MetaMap)
+ , m_file(NULL)
+{
+ /* Although it is safe, it may not be good to have this here, could be done
+ * once instead of everytime we read a file. */
+ openvdb::initialize();
+}
+
+OpenVDBReader::~OpenVDBReader()
+{
+ cleanupFile();
+}
+
+void OpenVDBReader::open(const openvdb::Name &filename)
+{
+ cleanupFile();
+
+ try {
+ m_file = new openvdb::io::File(filename);
+ m_file->setCopyMaxBytes(0);
+ m_file->open();
+
+ m_meta_map = m_file->getMetadata();
+ }
+ /* Mostly to catch exceptions related to Blosc not being supported. */
+ catch (const openvdb::IoError &e) {
+ std::cerr << e.what() << '\n';
+ cleanupFile();
+ }
+}
+
+void OpenVDBReader::floatMeta(const openvdb::Name &name, float &value) const
+{
+ try {
+ value = m_meta_map->metaValue<float>(name);
+ }
+ CATCH_KEYERROR;
+}
+
+void OpenVDBReader::intMeta(const openvdb::Name &name, int &value) const
+{
+ try {
+ value = m_meta_map->metaValue<int>(name);
+ }
+ CATCH_KEYERROR;
+}
+
+void OpenVDBReader::vec3sMeta(const openvdb::Name &name, float value[3]) const
+{
+ try {
+ openvdb::Vec3s meta_val = m_meta_map->metaValue<openvdb::Vec3s>(name);
+
+ value[0] = meta_val.x();
+ value[1] = meta_val.y();
+ value[2] = meta_val.z();
+ }
+ CATCH_KEYERROR;
+}
+
+void OpenVDBReader::vec3IMeta(const openvdb::Name &name, int value[3]) const
+{
+ try {
+ openvdb::Vec3i meta_val = m_meta_map->metaValue<openvdb::Vec3i>(name);
+
+ value[0] = meta_val.x();
+ value[1] = meta_val.y();
+ value[2] = meta_val.z();
+ }
+ CATCH_KEYERROR;
+}
+
+void OpenVDBReader::mat4sMeta(const openvdb::Name &name, float value[4][4]) const
+{
+ try {
+ openvdb::Mat4s meta_val = m_meta_map->metaValue<openvdb::Mat4s>(name);
+
+ for (int i = 0; i < 4; ++i) {
+ for (int j = 0; j < 4; ++j) {
+ value[i][j] = meta_val[i][j];
+ }
+ }
+ }
+ CATCH_KEYERROR;
+}
+
+bool OpenVDBReader::hasGrid(const openvdb::Name &name) const
+{
+ return m_file->hasGrid(name);
+}
+
+openvdb::GridBase::Ptr OpenVDBReader::getGrid(const openvdb::Name &name) const
+{
+ return m_file->readGrid(name);
+}
+
+size_t OpenVDBReader::numGrids() const
+{
+ return m_file->getGrids()->size();
+}
+
+void OpenVDBReader::cleanupFile()
+{
+ if (m_file) {
+ m_file->close();
+ delete m_file;
+ }
+}
diff --git a/intern/openvdb/intern/openvdb_reader.h b/intern/openvdb/intern/openvdb_reader.h
new file mode 100644
index 00000000000..07f77130ff9
--- /dev/null
+++ b/intern/openvdb/intern/openvdb_reader.h
@@ -0,0 +1,55 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __OPENVDB_READER_H__
+#define __OPENVDB_READER_H__
+
+#include <openvdb/openvdb.h>
+
+struct OpenVDBReader {
+private:
+ openvdb::MetaMap::Ptr m_meta_map;
+ openvdb::io::File *m_file;
+
+ void cleanupFile();
+
+public:
+ OpenVDBReader();
+ ~OpenVDBReader();
+
+ void open(const openvdb::Name &filename);
+
+ void floatMeta(const openvdb::Name &name, float &value) const;
+ void intMeta(const openvdb::Name &name, int &value) const;
+ void vec3sMeta(const openvdb::Name &name, float value[3]) const;
+ void vec3IMeta(const openvdb::Name &name, int value[3]) const;
+ void mat4sMeta(const openvdb::Name &name, float value[4][4]) const;
+
+ bool hasGrid(const openvdb::Name &name) const;
+ openvdb::GridBase::Ptr getGrid(const openvdb::Name &name) const;
+ size_t numGrids() const;
+};
+
+#endif /* __OPENVDB_READER_H__ */
diff --git a/intern/openvdb/intern/openvdb_writer.cc b/intern/openvdb/intern/openvdb_writer.cc
new file mode 100644
index 00000000000..923752909d9
--- /dev/null
+++ b/intern/openvdb/intern/openvdb_writer.cc
@@ -0,0 +1,118 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "openvdb_writer.h"
+#include "openvdb_util.h"
+
+OpenVDBWriter::OpenVDBWriter()
+ : m_grids(new openvdb::GridPtrVec())
+ , m_meta_map(new openvdb::MetaMap())
+ , m_save_as_half(false)
+{
+ m_meta_map->insertMeta("creator", openvdb::StringMetadata("Blender/Smoke"));
+}
+
+OpenVDBWriter::~OpenVDBWriter()
+{}
+
+void OpenVDBWriter::insert(const openvdb::GridBase::Ptr &grid)
+{
+ grid->setSaveFloatAsHalf(m_save_as_half);
+ m_grids->push_back(grid);
+}
+
+void OpenVDBWriter::insert(const openvdb::GridBase &grid)
+{
+ m_grids->push_back(grid.copyGrid());
+}
+
+void OpenVDBWriter::insertFloatMeta(const openvdb::Name &name, const float value)
+{
+ try {
+ m_meta_map->insertMeta(name, openvdb::FloatMetadata(value));
+ }
+ CATCH_KEYERROR;
+}
+
+void OpenVDBWriter::insertIntMeta(const openvdb::Name &name, const int value)
+{
+ try {
+ m_meta_map->insertMeta(name, openvdb::Int32Metadata(value));
+ }
+ CATCH_KEYERROR;
+}
+
+void OpenVDBWriter::insertVec3sMeta(const openvdb::Name &name, const openvdb::Vec3s &value)
+{
+ try {
+ m_meta_map->insertMeta(name, openvdb::Vec3SMetadata(value));
+ }
+ CATCH_KEYERROR;
+}
+
+void OpenVDBWriter::insertVec3IMeta(const openvdb::Name &name, const openvdb::Vec3I &value)
+{
+ try {
+ m_meta_map->insertMeta(name, openvdb::Vec3IMetadata(value));
+ }
+ CATCH_KEYERROR;
+}
+
+void OpenVDBWriter::insertMat4sMeta(const openvdb::Name &name, const float value[4][4])
+{
+ openvdb::Mat4s mat = openvdb::Mat4s(
+ value[0][0], value[0][1], value[0][2], value[0][3],
+ value[1][0], value[1][1], value[1][2], value[1][3],
+ value[2][0], value[2][1], value[2][2], value[2][3],
+ value[3][0], value[3][1], value[3][2], value[3][3]);
+
+ try {
+ m_meta_map->insertMeta(name, openvdb::Mat4SMetadata(mat));
+ }
+ CATCH_KEYERROR;
+}
+
+void OpenVDBWriter::setFlags(const int compression, const bool save_as_half)
+{
+ m_compression_flags = compression;
+ m_save_as_half = save_as_half;
+}
+
+void OpenVDBWriter::write(const openvdb::Name &filename) const
+{
+ try {
+ openvdb::io::File file(filename);
+ file.setCompression(m_compression_flags);
+ file.write(*m_grids, *m_meta_map);
+ file.close();
+
+ /* Should perhaps be an option at some point */
+ m_grids->clear();
+ }
+ /* Mostly to catch exceptions related to Blosc not being supported. */
+ catch (const openvdb::IoError &e) {
+ std::cerr << e.what() << '\n';
+ }
+}
diff --git a/intern/openvdb/intern/openvdb_writer.h b/intern/openvdb/intern/openvdb_writer.h
new file mode 100644
index 00000000000..69f42473975
--- /dev/null
+++ b/intern/openvdb/intern/openvdb_writer.h
@@ -0,0 +1,57 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __OPENVDB_WRITER_H__
+#define __OPENVDB_WRITER_H__
+
+#include <openvdb/openvdb.h>
+
+struct OpenVDBWriter {
+private:
+ openvdb::GridPtrVecPtr m_grids;
+ openvdb::MetaMap::Ptr m_meta_map;
+
+ int m_compression_flags;
+ bool m_save_as_half;
+
+public:
+ OpenVDBWriter();
+ ~OpenVDBWriter();
+
+ void insert(const openvdb::GridBase::Ptr &grid);
+ void insert(const openvdb::GridBase &grid);
+
+ void insertFloatMeta(const openvdb::Name &name, const float value);
+ void insertIntMeta(const openvdb::Name &name, const int value);
+ void insertVec3sMeta(const openvdb::Name &name, const openvdb::Vec3s &value);
+ void insertVec3IMeta(const openvdb::Name &name, const openvdb::Vec3I &value);
+ void insertMat4sMeta(const openvdb::Name &name, const float value[4][4]);
+
+ void setFlags(const int compression, const bool save_as_half);
+
+ void write(const openvdb::Name &filename) const;
+};
+
+#endif /* __OPENVDB_WRITER_H__ */
diff --git a/intern/openvdb/openvdb_capi.cc b/intern/openvdb/openvdb_capi.cc
new file mode 100644
index 00000000000..ef4f8c8820f
--- /dev/null
+++ b/intern/openvdb/openvdb_capi.cc
@@ -0,0 +1,240 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "openvdb_capi.h"
+#include "openvdb_dense_convert.h"
+#include "openvdb_util.h"
+
+struct OpenVDBFloatGrid { int unused; };
+struct OpenVDBIntGrid { int unused; };
+struct OpenVDBVectorGrid { int unused; };
+
+int OpenVDB_getVersionHex()
+{
+ return openvdb::OPENVDB_LIBRARY_VERSION;
+}
+
+OpenVDBFloatGrid *OpenVDB_export_grid_fl(
+ OpenVDBWriter *writer,
+ const char *name, float *data,
+ const int res[3], float matrix[4][4],
+ OpenVDBFloatGrid *mask)
+{
+ Timer(__func__);
+
+ using openvdb::FloatGrid;
+
+ FloatGrid *mask_grid = reinterpret_cast<FloatGrid *>(mask);
+ FloatGrid *grid = internal::OpenVDB_export_grid<FloatGrid>(
+ writer,
+ name,
+ data,
+ res,
+ matrix,
+ mask_grid);
+
+ return reinterpret_cast<OpenVDBFloatGrid *>(grid);
+}
+
+OpenVDBIntGrid *OpenVDB_export_grid_ch(
+ OpenVDBWriter *writer,
+ const char *name, unsigned char *data,
+ const int res[3], float matrix[4][4],
+ OpenVDBFloatGrid *mask)
+{
+ Timer(__func__);
+
+ using openvdb::FloatGrid;
+ using openvdb::Int32Grid;
+
+ FloatGrid *mask_grid = reinterpret_cast<FloatGrid *>(mask);
+ Int32Grid *grid = internal::OpenVDB_export_grid<Int32Grid>(
+ writer,
+ name,
+ data,
+ res,
+ matrix,
+ mask_grid);
+
+ return reinterpret_cast<OpenVDBIntGrid *>(grid);
+}
+
+OpenVDBVectorGrid *OpenVDB_export_grid_vec(
+ struct OpenVDBWriter *writer,
+ const char *name,
+ const float *data_x, const float *data_y, const float *data_z,
+ const int res[3], float matrix[4][4], short vec_type,
+ const bool is_color, OpenVDBFloatGrid *mask)
+{
+ Timer(__func__);
+
+ using openvdb::GridBase;
+ using openvdb::FloatGrid;
+ using openvdb::VecType;
+
+ FloatGrid *mask_grid = reinterpret_cast<FloatGrid *>(mask);
+ GridBase *grid = internal::OpenVDB_export_vector_grid(
+ writer,
+ name,
+ data_x,
+ data_y,
+ data_z,
+ res,
+ matrix,
+ static_cast<VecType>(vec_type),
+ is_color,
+ mask_grid);
+
+ return reinterpret_cast<OpenVDBVectorGrid *>(grid);
+}
+
+void OpenVDB_import_grid_fl(
+ OpenVDBReader *reader,
+ const char *name, float **data,
+ const int res[3])
+{
+ Timer(__func__);
+
+ internal::OpenVDB_import_grid<openvdb::FloatGrid>(reader, name, data, res);
+}
+
+void OpenVDB_import_grid_ch(
+ OpenVDBReader *reader,
+ const char *name, unsigned char **data,
+ const int res[3])
+{
+ internal::OpenVDB_import_grid<openvdb::Int32Grid>(reader, name, data, res);
+}
+
+void OpenVDB_import_grid_vec(
+ struct OpenVDBReader *reader,
+ const char *name,
+ float **data_x, float **data_y, float **data_z,
+ const int res[3])
+{
+ Timer(__func__);
+
+ internal::OpenVDB_import_grid_vector(reader, name, data_x, data_y, data_z, res);
+}
+
+OpenVDBWriter *OpenVDBWriter_create()
+{
+ return new OpenVDBWriter();
+}
+
+void OpenVDBWriter_free(OpenVDBWriter *writer)
+{
+ delete writer;
+}
+
+void OpenVDBWriter_set_flags(OpenVDBWriter *writer, const int flag, const bool half)
+{
+ int compression_flags = openvdb::io::COMPRESS_ACTIVE_MASK;
+
+#ifdef WITH_OPENVDB_BLOSC
+ if (flag == 0) {
+ compression_flags |= openvdb::io::COMPRESS_BLOSC;
+ }
+ else
+#endif
+ if (flag == 1) {
+ compression_flags |= openvdb::io::COMPRESS_ZIP;
+ }
+ else {
+ compression_flags = openvdb::io::COMPRESS_NONE;
+ }
+
+ writer->setFlags(compression_flags, half);
+}
+
+void OpenVDBWriter_add_meta_fl(OpenVDBWriter *writer, const char *name, const float value)
+{
+ writer->insertFloatMeta(name, value);
+}
+
+void OpenVDBWriter_add_meta_int(OpenVDBWriter *writer, const char *name, const int value)
+{
+ writer->insertIntMeta(name, value);
+}
+
+void OpenVDBWriter_add_meta_v3(OpenVDBWriter *writer, const char *name, const float value[3])
+{
+ writer->insertVec3sMeta(name, value);
+}
+
+void OpenVDBWriter_add_meta_v3_int(OpenVDBWriter *writer, const char *name, const int value[3])
+{
+ writer->insertVec3IMeta(name, value);
+}
+
+void OpenVDBWriter_add_meta_mat4(OpenVDBWriter *writer, const char *name, float value[4][4])
+{
+ writer->insertMat4sMeta(name, value);
+}
+
+void OpenVDBWriter_write(OpenVDBWriter *writer, const char *filename)
+{
+ writer->write(filename);
+}
+
+OpenVDBReader *OpenVDBReader_create()
+{
+ return new OpenVDBReader();
+}
+
+void OpenVDBReader_free(OpenVDBReader *reader)
+{
+ delete reader;
+}
+
+void OpenVDBReader_open(OpenVDBReader *reader, const char *filename)
+{
+ reader->open(filename);
+}
+
+void OpenVDBReader_get_meta_fl(OpenVDBReader *reader, const char *name, float *value)
+{
+ reader->floatMeta(name, *value);
+}
+
+void OpenVDBReader_get_meta_int(OpenVDBReader *reader, const char *name, int *value)
+{
+ reader->intMeta(name, *value);
+}
+
+void OpenVDBReader_get_meta_v3(OpenVDBReader *reader, const char *name, float value[3])
+{
+ reader->vec3sMeta(name, value);
+}
+
+void OpenVDBReader_get_meta_v3_int(OpenVDBReader *reader, const char *name, int value[3])
+{
+ reader->vec3IMeta(name, value);
+}
+
+void OpenVDBReader_get_meta_mat4(OpenVDBReader *reader, const char *name, float value[4][4])
+{
+ reader->mat4sMeta(name, value);
+}
diff --git a/intern/openvdb/openvdb_capi.h b/intern/openvdb/openvdb_capi.h
new file mode 100644
index 00000000000..2d2feeadcf1
--- /dev/null
+++ b/intern/openvdb/openvdb_capi.h
@@ -0,0 +1,108 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __OPENVDB_CAPI_H__
+#define __OPENVDB_CAPI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct OpenVDBReader;
+struct OpenVDBWriter;
+struct OpenVDBFloatGrid;
+struct OpenVDBIntGrid;
+struct OpenVDBVectorGrid;
+
+int OpenVDB_getVersionHex(void);
+
+enum {
+ VEC_INVARIANT = 0,
+ VEC_COVARIANT = 1,
+ VEC_COVARIANT_NORMALIZE = 2,
+ VEC_CONTRAVARIANT_RELATIVE = 3,
+ VEC_CONTRAVARIANT_ABSOLUTE = 4,
+};
+
+struct OpenVDBFloatGrid *OpenVDB_export_grid_fl(
+ struct OpenVDBWriter *writer,
+ const char *name, float *data,
+ const int res[3], float matrix[4][4],
+ struct OpenVDBFloatGrid *mask);
+
+struct OpenVDBIntGrid *OpenVDB_export_grid_ch(
+ struct OpenVDBWriter *writer,
+ const char *name, unsigned char *data,
+ const int res[3], float matrix[4][4],
+ struct OpenVDBFloatGrid *mask);
+
+struct OpenVDBVectorGrid *OpenVDB_export_grid_vec(
+ struct OpenVDBWriter *writer,
+ const char *name,
+ const float *data_x, const float *data_y, const float *data_z,
+ const int res[3], float matrix[4][4], short vec_type,
+ const bool is_color,
+ struct OpenVDBFloatGrid *mask);
+
+void OpenVDB_import_grid_fl(
+ struct OpenVDBReader *reader,
+ const char *name, float **data,
+ const int res[3]);
+
+void OpenVDB_import_grid_ch(
+ struct OpenVDBReader *reader,
+ const char *name, unsigned char **data,
+ const int res[3]);
+
+void OpenVDB_import_grid_vec(
+ struct OpenVDBReader *reader,
+ const char *name,
+ float **data_x, float **data_y, float **data_z,
+ const int res[3]);
+
+struct OpenVDBWriter *OpenVDBWriter_create(void);
+void OpenVDBWriter_free(struct OpenVDBWriter *writer);
+void OpenVDBWriter_set_flags(struct OpenVDBWriter *writer, const int flag, const bool half);
+void OpenVDBWriter_add_meta_fl(struct OpenVDBWriter *writer, const char *name, const float value);
+void OpenVDBWriter_add_meta_int(struct OpenVDBWriter *writer, const char *name, const int value);
+void OpenVDBWriter_add_meta_v3(struct OpenVDBWriter *writer, const char *name, const float value[3]);
+void OpenVDBWriter_add_meta_v3_int(struct OpenVDBWriter *writer, const char *name, const int value[3]);
+void OpenVDBWriter_add_meta_mat4(struct OpenVDBWriter *writer, const char *name, float value[4][4]);
+void OpenVDBWriter_write(struct OpenVDBWriter *writer, const char *filename);
+
+struct OpenVDBReader *OpenVDBReader_create(void);
+void OpenVDBReader_free(struct OpenVDBReader *reader);
+void OpenVDBReader_open(struct OpenVDBReader *reader, const char *filename);
+void OpenVDBReader_get_meta_fl(struct OpenVDBReader *reader, const char *name, float *value);
+void OpenVDBReader_get_meta_int(struct OpenVDBReader *reader, const char *name, int *value);
+void OpenVDBReader_get_meta_v3(struct OpenVDBReader *reader, const char *name, float value[3]);
+void OpenVDBReader_get_meta_v3_int(struct OpenVDBReader *reader, const char *name, int value[3]);
+void OpenVDBReader_get_meta_mat4(struct OpenVDBReader *reader, const char *name, float value[4][4]);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OPENVDB_CAPI_H__ */
diff --git a/intern/openvdb/openvdb_util.cc b/intern/openvdb/openvdb_util.cc
new file mode 100644
index 00000000000..d187f55970d
--- /dev/null
+++ b/intern/openvdb/openvdb_util.cc
@@ -0,0 +1,38 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "openvdb_util.h"
+
+#include <cstdio>
+
+ScopeTimer::ScopeTimer(const std::string &message)
+ : m_message(message)
+ , m_timer()
+{}
+
+ScopeTimer::~ScopeTimer()
+{
+ std::printf("%s: %fms\n", m_message.c_str(), m_timer.delta());
+}
diff --git a/intern/openvdb/openvdb_util.h b/intern/openvdb/openvdb_util.h
new file mode 100644
index 00000000000..8e14ed54345
--- /dev/null
+++ b/intern/openvdb/openvdb_util.h
@@ -0,0 +1,57 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __OPENVDB_UTIL_H__
+#define __OPENVDB_UTIL_H__
+
+#include <openvdb/openvdb.h>
+#include <openvdb/util/CpuTimer.h>
+
+#define CATCH_KEYERROR \
+ catch (const openvdb::KeyError &e) { \
+ std::cerr << e.what() << '\n'; \
+ }
+
+//#define DEBUG_TIME
+
+/* A utility class which prints the time elapsed during its lifetime, useful for
+ * e.g. timing the overall execution time of a function */
+class ScopeTimer {
+ std::string m_message;
+ openvdb::util::CpuTimer m_timer;
+
+public:
+ ScopeTimer(const std::string &message);
+ ~ScopeTimer();
+};
+
+#ifdef DEBUG_TIME
+# define Timer(x) \
+ ScopeTimer prof(x);
+#else
+# define Timer(x)
+#endif
+
+#endif /* __OPENVDB_UTIL_H__ */
diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py
index c4b2d9ff897..382cb181d5f 100644
--- a/release/scripts/modules/sys_info.py
+++ b/release/scripts/modules/sys_info.py
@@ -151,6 +151,13 @@ def write_sysinfo(filepath):
else:
output.write("Blender was built without Cycles support\n")
+ openvdb = bpy.app.openvdb
+ output.write("OpenVDB: ")
+ if openvdb.supported:
+ output.write("%s\n" % openvdb.version_string)
+ else:
+ output.write("Blender was built without OpenVDB support\n")
+
if not bpy.app.build_options.sdl:
output.write("SDL: Blender was built without SDL support\n")
diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py
index 85d3c1d7dc4..32d5b287d83 100644
--- a/release/scripts/startup/bl_ui/properties_physics_smoke.py
+++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py
@@ -304,12 +304,26 @@ class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
- md = context.smoke.domain_settings
- cache = md.point_cache
+ domain = context.smoke.domain_settings
+ cache_file_format = domain.cache_file_format
+
+ layout.prop(domain, "cache_file_format")
+
+ if cache_file_format == 'POINTCACHE':
+ layout.label(text="Compression:")
+ layout.prop(domain, "point_cache_compress_type", expand=True)
+ elif cache_file_format == 'OPENVDB':
+ if not bpy.app.build_options.openvdb:
+ layout.label("Build without OpenVDB support.")
+ return
- layout.label(text="Compression:")
- layout.prop(md, "point_cache_compress_type", expand=True)
+ layout.label(text="Compression:")
+ layout.prop(domain, "openvdb_cache_compress_type", expand=True)
+ row = layout.row()
+ row.label("Data Depth:")
+ row.prop(domain, "data_depth", expand=True, text="Data Depth")
+ cache = domain.point_cache
point_cache_ui(self, context, cache, (cache.is_baked is False), 'SMOKE')
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index d1b8aa672c5..40dbffe7222 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -94,6 +94,9 @@ struct SmokeModifierData;
struct SoftBody;
struct RigidBodyWorld;
+struct OpenVDBReader;
+struct OpenVDBWriter;
+
/* temp structure for read/write */
typedef struct PTCacheData {
unsigned int index;
@@ -119,13 +122,18 @@ typedef struct PTCacheFile {
#define PTCACHE_VEL_PER_SEC 1
+enum {
+ PTCACHE_FILE_PTCACHE = 0,
+ PTCACHE_FILE_OPENVDB = 1,
+};
+
typedef struct PTCacheID {
struct PTCacheID *next, *prev;
struct Scene *scene;
struct Object *ob;
void *calldata;
- unsigned int type;
+ unsigned int type, file_type;
unsigned int stack_index;
unsigned int flag;
@@ -147,6 +155,11 @@ typedef struct PTCacheID {
/* copies cache cata to point data */
int (*read_stream)(PTCacheFile *pf, void *calldata);
+ /* copies point data to cache data */
+ int (*write_openvdb_stream)(struct OpenVDBWriter *writer, void *calldata);
+ /* copies cache cata to point data */
+ int (*read_openvdb_stream)(struct OpenVDBReader *reader, void *calldata);
+
/* copies custom extradata to cache data */
void (*write_extra_data)(void *calldata, struct PTCacheMem *pm, int cfra);
/* copies custom extradata to cache data */
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 3ba6eb6c66d..b0a105bb910 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -517,6 +517,19 @@ if(WITH_OPENSUBDIV)
endif()
endif()
+if(WITH_OPENVDB)
+ add_definitions(-DWITH_OPENVDB)
+ list(APPEND INC
+ ../../../intern/openvdb
+ )
+
+ if(WITH_OPENVDB_BLOSC)
+ add_definitions(
+ -DWITH_OPENVDB_BLOSC
+ )
+ endif()
+endif()
+
## Warnings as errors, this is too strict!
#if(MSVC)
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index ad599942b50..8d6edcec0c7 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -83,6 +83,10 @@
#include "smoke_API.h"
#endif
+#ifdef WITH_OPENVDB
+#include "openvdb_capi.h"
+#endif
+
#ifdef WITH_LZO
# ifdef WITH_SYSTEM_LZO
# include <lzo/lzo1x.h>
@@ -887,6 +891,274 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v)
return 1;
}
+#ifdef WITH_OPENVDB
+/**
+ * Construct matrices which represent the fluid object, for low and high res:
+ * <pre>
+ * vs 0 0 0
+ * 0 vs 0 0
+ * 0 0 vs 0
+ * px py pz 1
+ * </pre>
+ *
+ * with `vs` = voxel size, and `px, py, pz`,
+ * the min position of the domain's bounding box.
+ */
+static void compute_fluid_matrices(SmokeDomainSettings *sds)
+{
+ float bbox_min[3];
+
+ copy_v3_v3(bbox_min, sds->p0);
+
+ if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
+ bbox_min[0] += (sds->cell_size[0] * (float)sds->res_min[0]);
+ bbox_min[1] += (sds->cell_size[1] * (float)sds->res_min[1]);
+ bbox_min[2] += (sds->cell_size[2] * (float)sds->res_min[2]);
+ add_v3_v3(bbox_min, sds->obj_shift_f);
+ }
+
+ /* construct low res matrix */
+ size_to_mat4(sds->fluidmat, sds->cell_size);
+ copy_v3_v3(sds->fluidmat[3], bbox_min);
+
+ /* The smoke simulator stores voxels cell-centered, whilst VDB is node
+ * centered, so we offset the matrix by half a voxel to compensate. */
+ madd_v3_v3fl(sds->fluidmat[3], sds->cell_size, 0.5f);
+
+ mul_m4_m4m4(sds->fluidmat, sds->obmat, sds->fluidmat);
+
+ if (sds->wt) {
+ float voxel_size_high[3];
+ /* construct high res matrix */
+ mul_v3_v3fl(voxel_size_high, sds->cell_size, 1.0f / (float)(sds->amplify + 1));
+ size_to_mat4(sds->fluidmat_wt, voxel_size_high);
+ copy_v3_v3(sds->fluidmat_wt[3], bbox_min);
+
+ /* Same here, add half a voxel to adjust the position of the fluid. */
+ madd_v3_v3fl(sds->fluidmat_wt[3], voxel_size_high, 0.5f);
+
+ mul_m4_m4m4(sds->fluidmat_wt, sds->obmat, sds->fluidmat_wt);
+ }
+}
+
+static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke_v)
+{
+ SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
+ SmokeDomainSettings *sds = smd->domain;
+
+ OpenVDBWriter_set_flags(writer, sds->openvdb_comp, (sds->data_depth == 16));
+
+ OpenVDBWriter_add_meta_int(writer, "blender/smoke/active_fields", sds->active_fields);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/resolution", sds->res);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/min_resolution", sds->res_min);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/max_resolution", sds->res_max);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/base_resolution", sds->base_res);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/min_bbox", sds->p0);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/max_bbox", sds->p1);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/dp0", sds->dp0);
+ OpenVDBWriter_add_meta_v3_int(writer, "blender/smoke/shift", sds->shift);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/obj_shift_f", sds->obj_shift_f);
+ OpenVDBWriter_add_meta_v3(writer, "blender/smoke/active_color", sds->active_color);
+ OpenVDBWriter_add_meta_mat4(writer, "blender/smoke/obmat", sds->obmat);
+
+ int fluid_fields = smoke_get_data_flags(sds);
+
+ struct OpenVDBFloatGrid *clip_grid = NULL;
+
+ compute_fluid_matrices(sds);
+
+ OpenVDBWriter_add_meta_int(writer, "blender/smoke/fluid_fields", fluid_fields);
+
+ if (sds->wt) {
+ struct OpenVDBFloatGrid *wt_density_grid;
+ float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
+
+ smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
+
+ wt_density_grid = OpenVDB_export_grid_fl(writer, "density", dens, sds->res_wt, sds->fluidmat_wt, NULL);
+ clip_grid = wt_density_grid;
+
+ if (fluid_fields & SM_ACTIVE_FIRE) {
+ OpenVDB_export_grid_fl(writer, "flame", flame, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
+ OpenVDB_export_grid_fl(writer, "fuel", fuel, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
+ OpenVDB_export_grid_fl(writer, "react", react, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
+ }
+
+ if (fluid_fields & SM_ACTIVE_COLORS) {
+ OpenVDB_export_grid_vec(writer, "color", r, g, b, sds->res_wt, sds->fluidmat_wt, VEC_INVARIANT, true, wt_density_grid);
+ }
+
+ OpenVDB_export_grid_vec(writer, "texture coordinates", tcu, tcv, tcw, sds->res, sds->fluidmat, VEC_INVARIANT, false, wt_density_grid);
+ }
+
+ if (sds->fluid) {
+ struct OpenVDBFloatGrid *density_grid;
+ float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
+ unsigned char *obstacles;
+
+ smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat,
+ &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
+
+ OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dx", dx);
+ OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dt", dt);
+
+ const char *name = (!sds->wt) ? "density" : "density low";
+ density_grid = OpenVDB_export_grid_fl(writer, name, dens, sds->res, sds->fluidmat, NULL);
+ clip_grid = sds->wt ? clip_grid : density_grid;
+
+ OpenVDB_export_grid_fl(writer, "shadow", sds->shadow, sds->res, sds->fluidmat, NULL);
+
+ if (fluid_fields & SM_ACTIVE_HEAT) {
+ OpenVDB_export_grid_fl(writer, "heat", heat, sds->res, sds->fluidmat, clip_grid);
+ OpenVDB_export_grid_fl(writer, "heat old", heatold, sds->res, sds->fluidmat, clip_grid);
+ }
+
+ if (fluid_fields & SM_ACTIVE_FIRE) {
+ name = (!sds->wt) ? "flame" : "flame low";
+ OpenVDB_export_grid_fl(writer, name, flame, sds->res, sds->fluidmat, density_grid);
+ name = (!sds->wt) ? "fuel" : "fuel low";
+ OpenVDB_export_grid_fl(writer, name, fuel, sds->res, sds->fluidmat, density_grid);
+ name = (!sds->wt) ? "react" : "react low";
+ OpenVDB_export_grid_fl(writer, name, react, sds->res, sds->fluidmat, density_grid);
+ }
+
+ if (fluid_fields & SM_ACTIVE_COLORS) {
+ name = (!sds->wt) ? "color" : "color low";
+ OpenVDB_export_grid_vec(writer, name, r, g, b, sds->res, sds->fluidmat, VEC_INVARIANT, true, density_grid);
+ }
+
+ OpenVDB_export_grid_vec(writer, "velocity", vx, vy, vz, sds->res, sds->fluidmat, VEC_CONTRAVARIANT_RELATIVE, false, clip_grid);
+ OpenVDB_export_grid_ch(writer, "obstacles", obstacles, sds->res, sds->fluidmat, NULL);
+ }
+
+ return 1;
+}
+
+static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_v)
+{
+ SmokeModifierData *smd = (SmokeModifierData *)smoke_v;
+
+ if (!smd) {
+ return 0;
+ }
+
+ SmokeDomainSettings *sds = smd->domain;
+
+ int fluid_fields = smoke_get_data_flags(sds);
+ int active_fields, cache_fields = 0;
+ int cache_res[3];
+ float cache_dx;
+ bool reallocate = false;
+
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/min_resolution", sds->res_min);
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/max_resolution", sds->res_max);
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/base_resolution", sds->base_res);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/min_bbox", sds->p0);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/max_bbox", sds->p1);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/dp0", sds->dp0);
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/shift", sds->shift);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/obj_shift_f", sds->obj_shift_f);
+ OpenVDBReader_get_meta_v3(reader, "blender/smoke/active_color", sds->active_color);
+ OpenVDBReader_get_meta_mat4(reader, "blender/smoke/obmat", sds->obmat);
+ OpenVDBReader_get_meta_int(reader, "blender/smoke/fluid_fields", &cache_fields);
+ OpenVDBReader_get_meta_int(reader, "blender/smoke/active_fields", &active_fields);
+ OpenVDBReader_get_meta_fl(reader, "blender/smoke/dx", &cache_dx);
+ OpenVDBReader_get_meta_v3_int(reader, "blender/smoke/resolution", cache_res);
+
+ /* check if resolution has changed */
+ if (sds->res[0] != cache_res[0] ||
+ sds->res[1] != cache_res[1] ||
+ sds->res[2] != cache_res[2])
+ {
+ if (sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) {
+ reallocate = true;
+ }
+ else {
+ return 0;
+ }
+ }
+
+ /* check if active fields have changed */
+ if ((fluid_fields != cache_fields) || (active_fields != sds->active_fields)) {
+ reallocate = true;
+ }
+
+ /* reallocate fluid if needed*/
+ if (reallocate) {
+ sds->active_fields = active_fields | cache_fields;
+ smoke_reallocate_fluid(sds, cache_dx, cache_res, 1);
+ sds->dx = cache_dx;
+ copy_v3_v3_int(sds->res, cache_res);
+ sds->total_cells = cache_res[0] * cache_res[1] * cache_res[2];
+
+ if (sds->flags & MOD_SMOKE_HIGHRES) {
+ smoke_reallocate_highres_fluid(sds, cache_dx, cache_res, 1);
+ }
+ }
+
+ if (sds->fluid) {
+ float dt, dx, *dens, *react, *fuel, *flame, *heat, *heatold, *vx, *vy, *vz, *r, *g, *b;
+ unsigned char *obstacles;
+
+ smoke_export(sds->fluid, &dt, &dx, &dens, &react, &flame, &fuel, &heat,
+ &heatold, &vx, &vy, &vz, &r, &g, &b, &obstacles);
+
+ OpenVDBReader_get_meta_fl(reader, "blender/smoke/dt", &dt);
+
+ OpenVDB_import_grid_fl(reader, "shadow", &sds->shadow, sds->res);
+
+ const char *name = (!sds->wt) ? "density" : "density Low";
+ OpenVDB_import_grid_fl(reader, name, &dens, sds->res);
+
+ if (fluid_fields & SM_ACTIVE_HEAT) {
+ OpenVDB_import_grid_fl(reader, "heat", &heat, sds->res);
+ OpenVDB_import_grid_fl(reader, "heat old", &heatold, sds->res);
+ }
+
+ if (fluid_fields & SM_ACTIVE_FIRE) {
+ name = (!sds->wt) ? "flame" : "flame low";
+ OpenVDB_import_grid_fl(reader, name, &flame, sds->res);
+ name = (!sds->wt) ? "fuel" : "fuel low";
+ OpenVDB_import_grid_fl(reader, name, &fuel, sds->res);
+ name = (!sds->wt) ? "react" : "react low";
+ OpenVDB_import_grid_fl(reader, name, &react, sds->res);
+ }
+
+ if (fluid_fields & SM_ACTIVE_COLORS) {
+ name = (!sds->wt) ? "color" : "color low";
+ OpenVDB_import_grid_vec(reader, name, &r, &g, &b, sds->res);
+ }
+
+ OpenVDB_import_grid_vec(reader, "velocity", &vx, &vy, &vz, sds->res);
+ OpenVDB_import_grid_ch(reader, "obstacles", &obstacles, sds->res);
+ }
+
+ if (sds->wt) {
+ float *dens, *react, *fuel, *flame, *tcu, *tcv, *tcw, *r, *g, *b;
+
+ smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
+
+ OpenVDB_import_grid_fl(reader, "density", &dens, sds->res_wt);
+
+ if (fluid_fields & SM_ACTIVE_FIRE) {
+ OpenVDB_import_grid_fl(reader, "flame", &flame, sds->res_wt);
+ OpenVDB_import_grid_fl(reader, "fuel", &fuel, sds->res_wt);
+ OpenVDB_import_grid_fl(reader, "react", &react, sds->res_wt);
+ }
+
+ if (fluid_fields & SM_ACTIVE_COLORS) {
+ OpenVDB_import_grid_vec(reader, "color", &r, &g, &b, sds->res_wt);
+ }
+
+ OpenVDB_import_grid_vec(reader, "texture coordinates", &tcu, &tcv, &tcw, sds->res);
+ }
+
+ OpenVDBReader_free(reader);
+
+ return 1;
+}
+#endif
+
#else // WITH_SMOKE
static int ptcache_smoke_totpoint(void *UNUSED(smoke_v), int UNUSED(cfra)) { return 0; }
static void ptcache_smoke_error(void *UNUSED(smoke_v), const char *UNUSED(message)) { }
@@ -894,6 +1166,20 @@ static int ptcache_smoke_read(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) {
static int ptcache_smoke_write(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; }
#endif // WITH_SMOKE
+#if !defined(WITH_SMOKE) || !defined(WITH_OPENVDB)
+static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke_v)
+{
+ UNUSED_VARS(writer, smoke_v);
+ return 0;
+}
+
+static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_v)
+{
+ UNUSED_VARS(reader, smoke_v);
+ return 0;
+}
+#endif
+
static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra))
{
DynamicPaintSurface *surface = (DynamicPaintSurface*)sd;
@@ -1113,6 +1399,9 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
pid->write_stream = NULL;
pid->read_stream = NULL;
+ pid->write_openvdb_stream = NULL;
+ pid->read_openvdb_stream = NULL;
+
pid->write_extra_data = NULL;
pid->read_extra_data = NULL;
pid->interpolate_extra_data = NULL;
@@ -1127,6 +1416,7 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
pid->default_step = 10;
pid->max_step = 20;
+ pid->file_type = PTCACHE_FILE_PTCACHE;
}
void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
{
@@ -1154,6 +1444,9 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p
pid->write_stream = NULL;
pid->read_stream = NULL;
+ pid->write_openvdb_stream = NULL;
+ pid->read_openvdb_stream = NULL;
+
pid->write_extra_data = NULL;
pid->read_extra_data = NULL;
pid->interpolate_extra_data = NULL;
@@ -1185,6 +1478,7 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p
pid->default_step = 10;
pid->max_step = 20;
+ pid->file_type = PTCACHE_FILE_PTCACHE;
}
void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd)
{
@@ -1204,6 +1498,9 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl
pid->read_point = ptcache_cloth_read;
pid->interpolate_point = ptcache_cloth_interpolate;
+ pid->write_openvdb_stream = NULL;
+ pid->read_openvdb_stream = NULL;
+
pid->write_stream = NULL;
pid->read_stream = NULL;
@@ -1219,6 +1516,7 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl
pid->default_step = 1;
pid->max_step = 1;
+ pid->file_type = PTCACHE_FILE_PTCACHE;
}
void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd)
{
@@ -1246,6 +1544,9 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo
pid->read_stream = ptcache_smoke_read;
pid->write_stream = ptcache_smoke_write;
+ pid->write_openvdb_stream = ptcache_smoke_openvdb_write;
+ pid->read_openvdb_stream = ptcache_smoke_openvdb_read;
+
pid->write_extra_data = NULL;
pid->read_extra_data = NULL;
pid->interpolate_extra_data = NULL;
@@ -1263,6 +1564,7 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo
pid->default_step = 1;
pid->max_step = 1;
+ pid->file_type = smd->domain->cache_file_format;
}
void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSurface *surface)
@@ -1286,6 +1588,9 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSu
pid->write_stream = ptcache_dynamicpaint_write;
pid->read_stream = ptcache_dynamicpaint_read;
+ pid->write_openvdb_stream = NULL;
+ pid->read_openvdb_stream = NULL;
+
pid->write_extra_data = NULL;
pid->read_extra_data = NULL;
pid->interpolate_extra_data = NULL;
@@ -1300,6 +1605,7 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSu
pid->default_step = 1;
pid->max_step = 1;
+ pid->file_type = PTCACHE_FILE_PTCACHE;
}
void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *rbw)
@@ -1322,6 +1628,9 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r
pid->write_stream = NULL;
pid->read_stream = NULL;
+
+ pid->write_openvdb_stream = NULL;
+ pid->read_openvdb_stream = NULL;
pid->write_extra_data = NULL;
pid->read_extra_data = NULL;
@@ -1337,6 +1646,7 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r
pid->default_step = 1;
pid->max_step = 1;
+ pid->file_type = PTCACHE_FILE_PTCACHE;
}
void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
@@ -1429,6 +1739,38 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
/* File handling */
+static const char *ptcache_file_extension(const PTCacheID *pid)
+{
+ switch (pid->file_type) {
+ default:
+ case PTCACHE_FILE_PTCACHE:
+ return PTCACHE_EXT;
+ case PTCACHE_FILE_OPENVDB:
+ return ".vdb";
+ }
+}
+
+/**
+ * Similar to #BLI_path_frame_get, but takes into account the stack-index which is after the frame.
+ */
+static int ptcache_frame_from_filename(const char *filename, const char *ext)
+{
+ const int frame_len = 6;
+ const int ext_len = frame_len + strlen(ext);
+ const int len = strlen(filename);
+
+ /* could crash if trying to copy a string out of this range */
+ if (len > ext_len) {
+ /* using frame_len here gives compile error (vla) */
+ char num[/* frame_len */6 + 1];
+ BLI_strncpy(num, filename + len - ext_len, sizeof(num));
+
+ return atoi(num);
+ }
+
+ return -1;
+}
+
/* Takes an Object ID and returns a unique name
* - id: object id
* - cfra: frame for the cache, can be negative
@@ -1507,18 +1849,19 @@ static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_p
}
if (do_ext) {
-
if (pid->cache->index < 0)
pid->cache->index = pid->stack_index = BKE_object_insert_ptcache(pid->ob);
+ const char *ext = ptcache_file_extension(pid);
+
if (pid->cache->flag & PTCACHE_EXTERNAL) {
if (pid->cache->index >= 0)
- BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
+ BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u%s", cfra, pid->stack_index, ext); /* always 6 chars */
else
- BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */
+ BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d%s", cfra, ext); /* always 6 chars */
}
else {
- BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */
+ BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u%s", cfra, pid->stack_index, ext); /* always 6 chars */
}
len += 16;
}
@@ -2156,6 +2499,36 @@ static int ptcache_read_stream(PTCacheID *pid, int cfra)
return error == 0;
}
+
+static int ptcache_read_openvdb_stream(PTCacheID *pid, int cfra)
+{
+#ifdef WITH_OPENVDB
+ char filename[FILE_MAX * 2];
+
+ /* save blend file before using disk pointcache */
+ if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL) == 0)
+ return 0;
+
+ ptcache_filename(pid, filename, cfra, 1, 1);
+
+ if (!BLI_exists(filename)) {
+ return 0;
+ }
+
+ struct OpenVDBReader *reader = OpenVDBReader_create();
+ OpenVDBReader_open(reader, filename);
+
+ if (!pid->read_openvdb_stream(reader, pid->calldata)) {
+ return 0;
+ }
+
+ return 1;
+#else
+ UNUSED_VARS(pid, cfra);
+ return 0;
+#endif
+}
+
static int ptcache_read(PTCacheID *pid, int cfra)
{
PTCacheMem *pm = NULL;
@@ -2297,8 +2670,12 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra)
return 0;
if (cfra1) {
-
- if (pid->read_stream) {
+ if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->read_openvdb_stream) {
+ if (!ptcache_read_openvdb_stream(pid, cfra1)) {
+ return 0;
+ }
+ }
+ else if (pid->read_stream) {
if (!ptcache_read_stream(pid, cfra1))
return 0;
}
@@ -2307,8 +2684,12 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra)
}
if (cfra2) {
-
- if (pid->read_stream) {
+ if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->read_openvdb_stream) {
+ if (!ptcache_read_openvdb_stream(pid, cfra2)) {
+ return 0;
+ }
+ }
+ else if (pid->read_stream) {
if (!ptcache_read_stream(pid, cfra2))
return 0;
}
@@ -2374,6 +2755,28 @@ static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint)
return error == 0;
}
+static int ptcache_write_openvdb_stream(PTCacheID *pid, int cfra)
+{
+#ifdef WITH_OPENVDB
+ struct OpenVDBWriter *writer = OpenVDBWriter_create();
+ char filename[FILE_MAX * 2];
+
+ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra);
+
+ ptcache_filename(pid, filename, cfra, 1, 1);
+ BLI_make_existing_file(filename);
+
+ int error = pid->write_openvdb_stream(writer, pid->calldata);
+
+ OpenVDBWriter_write(writer, filename);
+ OpenVDBWriter_free(writer);
+
+ return error == 0;
+#else
+ UNUSED_VARS(pid, cfra);
+ return 0;
+#endif
+}
static int ptcache_write(PTCacheID *pid, int cfra, int overwrite)
{
PointCache *cache = pid->cache;
@@ -2505,7 +2908,10 @@ int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
if (ptcache_write_needed(pid, cfra, &overwrite)==0)
return 0;
- if (pid->write_stream) {
+ if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->write_openvdb_stream) {
+ ptcache_write_openvdb_stream(pid, cfra);
+ }
+ else if (pid->write_stream) {
ptcache_write_stream(pid, cfra, totpoint);
}
else if (pid->write_point) {
@@ -2563,7 +2969,9 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
#endif
/*if (!G.relbase_valid) return; *//* save blend file before using pointcache */
-
+
+ const char *fext = ptcache_file_extension(pid);
+
/* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */
switch (mode) {
case PTCACHE_CLEAR_ALL:
@@ -2585,7 +2993,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
len += 1;
}
- BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
+ BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
while ((de = readdir(dir)) != NULL) {
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
@@ -2597,13 +3005,9 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
}
else {
/* read the number of the file */
- unsigned int frame, len2 = (int)strlen(de->d_name);
- char num[7];
+ const int frame = ptcache_frame_from_filename(de->d_name, ext);
- if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
- BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
- frame = atoi(num);
-
+ if (frame != -1) {
if ((mode == PTCACHE_CLEAR_BEFORE && frame < cfra) ||
(mode == PTCACHE_CLEAR_AFTER && frame > cfra))
{
@@ -2791,21 +3195,18 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
if (dir==NULL)
return;
- BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
+ const char *fext = ptcache_file_extension(pid);
+
+ BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
while ((de = readdir(dir)) != NULL) {
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
/* read the number of the file */
- unsigned int frame, len2 = (int)strlen(de->d_name);
- char num[7];
-
- if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
- BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
- frame = atoi(num);
-
- if (frame >= sta && frame <= end)
- cache->cached_frames[frame-sta] = 1;
+ const int frame = ptcache_frame_from_filename(de->d_name, ext);
+
+ if ((frame != -1) && (frame >= sta && frame <= end)) {
+ cache->cached_frames[frame-sta] = 1;
}
}
}
@@ -3466,7 +3867,9 @@ void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const c
return;
}
- BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index);
+ const char *fext = ptcache_file_extension(pid);
+
+ BLI_snprintf(ext, sizeof(ext), "_%02u%s", pid->stack_index, fext);
/* put new name into cache */
BLI_strncpy(pid->cache->name, name_dst, sizeof(pid->cache->name));
@@ -3475,13 +3878,9 @@ void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const c
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
if (STREQLEN(old_filename, de->d_name, len)) { /* do we have the right prefix */
/* read the number of the file */
- int frame, len2 = (int)strlen(de->d_name);
- char num[7];
-
- if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
- BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
- frame = atoi(num);
+ const int frame = ptcache_frame_from_filename(de->d_name, ext);
+ if (frame != -1) {
BLI_join_dirfile(old_path_full, sizeof(old_path_full), path, de->d_name);
ptcache_filename(pid, new_path_full, frame, 1, 1);
BLI_rename(old_path_full, new_path_full);
@@ -3521,22 +3920,20 @@ void BKE_ptcache_load_external(PTCacheID *pid)
if (dir==NULL)
return;
+ const char *fext = ptcache_file_extension(pid);
+
if (cache->index >= 0)
- BLI_snprintf(ext, sizeof(ext), "_%02d"PTCACHE_EXT, cache->index);
+ BLI_snprintf(ext, sizeof(ext), "_%02d%s", cache->index, fext);
else
- BLI_strncpy(ext, PTCACHE_EXT, sizeof(ext));
+ BLI_strncpy(ext, fext, sizeof(ext));
while ((de = readdir(dir)) != NULL) {
if (strstr(de->d_name, ext)) { /* do we have the right extension?*/
if (STREQLEN(filename, de->d_name, len)) { /* do we have the right prefix */
/* read the number of the file */
- int frame, len2 = (int)strlen(de->d_name);
- char num[7];
-
- if (len2 > 15) { /* could crash if trying to copy a string out of this range*/
- BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num));
- frame = atoi(num);
+ const int frame = ptcache_frame_from_filename(de->d_name, ext);
+ if (frame != -1) {
if (frame) {
start = MIN2(start, frame);
end = MAX2(end, frame);
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 2d3fa2a3818..c7215cc7d4c 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -527,6 +527,14 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->viewsettings = MOD_SMOKE_VIEW_SHOWBIG;
smd->domain->effector_weights = BKE_add_effector_weights(NULL);
+
+#ifdef WITH_OPENVDB_BLOSC
+ smd->domain->openvdb_comp = VDB_COMPRESSION_BLOSC;
+#else
+ smd->domain->openvdb_comp = VDB_COMPRESSION_ZIP;
+#endif
+ smd->domain->data_depth = 0;
+ smd->domain->cache_file_format = PTCACHE_FILE_PTCACHE;
}
else if (smd->type & MOD_SMOKE_TYPE_FLOW)
{
@@ -617,6 +625,9 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData
MEM_freeN(tsmd->domain->effector_weights);
tsmd->domain->effector_weights = MEM_dupallocN(smd->domain->effector_weights);
+ tsmd->domain->openvdb_comp = smd->domain->openvdb_comp;
+ tsmd->domain->data_depth = smd->domain->data_depth;
+ tsmd->domain->cache_file_format = smd->domain->cache_file_format;
}
else if (tsmd->flow) {
tsmd->flow->psys = smd->flow->psys;
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 732d699d48f..84cb28b3fc0 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -7812,9 +7812,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
/* draw adaptive domain bounds */
if ((sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN) && !render_override) {
- float p0[3], p1[3];
- BoundBox bb;
/* draw domain max bounds */
+ BoundBox bb;
+ float p0[3], p1[3];
VECSUBFAC(p0, sds->p0, sds->cell_size, sds->adapt_res);
VECADDFAC(p1, sds->p1, sds->cell_size, sds->adapt_res);
BKE_boundbox_init_from_minmax(&bb, p0, p1);
@@ -7825,6 +7825,20 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
BKE_boundbox_init_from_minmax(&bb, sds->p0, sds->p1);
draw_box(bb.vec);
#endif
+
+
+ /* draw a single voxel to hint the user about the resolution of the fluid */
+ copy_v3_v3(p0, sds->p0);
+
+ if (sds->flags & MOD_SMOKE_HIGHRES) {
+ madd_v3_v3v3fl(p1, p0, sds->cell_size, 1.0f / (sds->amplify + 1));
+ }
+ else {
+ add_v3_v3v3(p1, p0, sds->cell_size);
+ }
+
+ BKE_boundbox_init_from_minmax(&bb, p0, p1);
+ draw_box(bb.vec, false);
}
/* don't show smoke before simulation starts, this could be made an option in the future */
diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h
index 5e011678fee..76de8443faa 100644
--- a/source/blender/makesdna/DNA_smoke_types.h
+++ b/source/blender/makesdna/DNA_smoke_types.h
@@ -77,6 +77,12 @@ enum {
#define SM_ACTIVE_COLORS (1<<2)
#define SM_ACTIVE_COLOR_SET (1<<3)
+enum {
+ VDB_COMPRESSION_BLOSC = 0,
+ VDB_COMPRESSION_ZIP = 1,
+ VDB_COMPRESSION_NONE = 2,
+};
+
typedef struct SmokeDomainSettings {
struct SmokeModifierData *smd; /* for fast RNA access */
struct FLUID_3D *fluid;
@@ -103,6 +109,8 @@ typedef struct SmokeDomainSettings {
float obj_shift_f[3]; /* how much object has shifted since previous smoke frame (used to "lock" domain while drawing) */
float imat[4][4]; /* domain object imat */
float obmat[4][4]; /* domain obmat */
+ float fluidmat[4][4]; /* low res fluid matrix */
+ float fluidmat_wt[4][4]; /* high res fluid matrix */
int base_res[3]; /* initial "non-adapted" resolution */
int res_min[3]; /* cell min */
@@ -129,8 +137,14 @@ typedef struct SmokeDomainSettings {
float strength;
int res_wt[3];
float dx_wt;
+ /* point cache options */
int cache_comp;
int cache_high_comp;
+ /* OpenVDB cache options */
+ int openvdb_comp;
+ char cache_file_format;
+ char data_depth;
+ char pad[2];
/* Smoke uses only one cache from now on (index [0]), but keeping the array for now for reading old files. */
struct PointCache *point_cache[2]; /* definition is in DNA_object_force.h */
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 987b594421f..31bf0c9389b 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -311,6 +311,14 @@ if(WITH_OPENSUBDIV)
add_definitions(-DWITH_OPENSUBDIV)
endif()
+if(WITH_OPENVDB)
+ add_definitions(-DWITH_OPENVDB)
+
+ if(WITH_OPENVDB_BLOSC)
+ add_definitions(-DWITH_OPENVDB_BLOSC)
+ endif()
+endif()
+
# Build makesrna executable
blender_include_dirs(
.
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index 539f3c192be..ba3198a4843 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -35,6 +35,7 @@
#include "BKE_modifier.h"
#include "BKE_smoke.h"
+#include "BKE_pointcache.h"
#include "BLI_threads.h"
@@ -332,6 +333,15 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem prop_compression_items[] = {
+ { VDB_COMPRESSION_ZIP, "ZIP", 0, "Zip", "Effective but slow compression" },
+#ifdef WITH_OPENVDB_BLOSC
+ { VDB_COMPRESSION_BLOSC, "BLOSC", 0, "Blosc", "Multithreaded compression, similar in size and quality as 'Zip'" },
+#endif
+ { VDB_COMPRESSION_NONE, "NONE", 0, "None", "Do not use any compression" },
+ { 0, NULL, 0, NULL, NULL }
+ };
+
static EnumPropertyItem smoke_cache_comp_items[] = {
{SM_CACHE_LIGHT, "CACHELIGHT", 0, "Light", "Fast but not so effective compression"},
{SM_CACHE_HEAVY, "CACHEHEAVY", 0, "Heavy", "Effective but slow compression"},
@@ -345,6 +355,12 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem smoke_data_depth_items[] = {
+ {16, "16", 0, "Float (Half)", "Half float (16 bit data)"},
+ {0, "32", 0, "Float (Full)", "Full float (32 bit data)"}, /* default */
+ {0, NULL, 0, NULL, NULL},
+ };
+
static EnumPropertyItem smoke_domain_colli_items[] = {
{SM_BORDER_OPEN, "BORDEROPEN", 0, "Open", "Smoke doesn't collide with any border"},
{SM_BORDER_VERTICAL, "BORDERVERTICAL", 0, "Vertically Open",
@@ -353,6 +369,14 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem cache_file_type_items[] = {
+ {PTCACHE_FILE_PTCACHE, "POINTCACHE", 0, "Point Cache", "Blender specific point cache file format"},
+#ifdef WITH_OPENVDB
+ {PTCACHE_FILE_OPENVDB, "OPENVDB", 0, "OpenVDB", "OpenVDB file format"},
+#endif
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "SmokeDomainSettings", NULL);
RNA_def_struct_ui_text(srna, "Domain Settings", "Smoke domain settings");
RNA_def_struct_sdna(srna, "SmokeDomainSettings");
@@ -463,6 +487,19 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
RNA_def_property_enum_items(prop, smoke_cache_comp_items);
RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used");
+ prop = RNA_def_property(srna, "openvdb_cache_compress_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "openvdb_comp");
+ RNA_def_property_enum_items(prop, prop_compression_items);
+ RNA_def_property_ui_text(prop, "Compression", "Compression method to be used");
+
+ prop = RNA_def_property(srna, "data_depth", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "data_depth");
+ RNA_def_property_enum_items(prop, smoke_data_depth_items);
+ RNA_def_property_ui_text(prop, "Data Depth",
+ "Bit depth for writing all scalar (including vector) "
+ "lower values reduce file size");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
+
prop = RNA_def_property(srna, "collision_extents", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "border_collisions");
RNA_def_property_enum_items(prop, smoke_domain_colli_items);
@@ -601,6 +638,12 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Threshold",
"Maximum amount of fluid cell can contain before it is considered empty");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
+
+ prop = RNA_def_property(srna, "cache_file_format", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "cache_file_format");
+ RNA_def_property_enum_items(prop, cache_file_type_items);
+ RNA_def_property_ui_text(prop, "File Format", "Select the file format to be used for caching");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Smoke_resetCache");
}
static void rna_def_smoke_flow_settings(BlenderRNA *brna)
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index cbfbe0a8768..5b39dbb062b 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -54,6 +54,7 @@ set(SRC
bpy_app_handlers.c
bpy_app_ocio.c
bpy_app_oiio.c
+ bpy_app_openvdb.c
bpy_app_sdl.c
bpy_app_translations.c
bpy_driver.c
@@ -84,6 +85,7 @@ set(SRC
bpy_app_handlers.h
bpy_app_ocio.h
bpy_app_oiio.h
+ bpy_app_openvdb.h
bpy_app_sdl.h
bpy_app_translations.h
bpy_driver.h
@@ -267,6 +269,13 @@ if(WITH_OPENCOLORIO)
add_definitions(-DWITH_OCIO)
endif()
+if(WITH_OPENVDB)
+ add_definitions(-DWITH_OPENVDB)
+ list(APPEND INC
+ ../../../../intern/openvdb
+ )
+endif()
+
if(WITH_OPENIMAGEIO)
add_definitions(-DWITH_OPENIMAGEIO)
list(APPEND INC
diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c
index a0ea991fd05..595bb7b0f22 100644
--- a/source/blender/python/intern/bpy_app.c
+++ b/source/blender/python/intern/bpy_app.c
@@ -36,6 +36,7 @@
#include "bpy_app_ffmpeg.h"
#include "bpy_app_ocio.h"
#include "bpy_app_oiio.h"
+#include "bpy_app_openvdb.h"
#include "bpy_app_sdl.h"
#include "bpy_app_build_options.h"
@@ -106,6 +107,7 @@ static PyStructSequence_Field app_info_fields[] = {
{(char *)"ffmpeg", (char *)"FFmpeg library information backend"},
{(char *)"ocio", (char *)"OpenColorIO library information backend"},
{(char *)"oiio", (char *)"OpenImageIO library information backend"},
+ {(char *)"openvdb", (char *)"OpenVDB library information backend"},
{(char *)"sdl", (char *)"SDL library information backend"},
{(char *)"build_options", (char *)"A set containing most important enabled optional build features"},
{(char *)"handlers", (char *)"Application handler callbacks"},
@@ -183,6 +185,7 @@ static PyObject *make_app_info(void)
SetObjItem(BPY_app_ffmpeg_struct());
SetObjItem(BPY_app_ocio_struct());
SetObjItem(BPY_app_oiio_struct());
+ SetObjItem(BPY_app_openvdb_struct());
SetObjItem(BPY_app_sdl_struct());
SetObjItem(BPY_app_build_options_struct());
SetObjItem(BPY_app_handlers_struct());
diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c
index 975d76ca42d..692ebf552c7 100644
--- a/source/blender/python/intern/bpy_app_build_options.c
+++ b/source/blender/python/intern/bpy_app_build_options.c
@@ -69,6 +69,7 @@ static PyStructSequence_Field app_builtopts_info_fields[] = {
{(char *)"opencolorio", NULL},
{(char *)"player", NULL},
{(char *)"openmp", NULL},
+ {(char *)"openvdb", NULL},
{NULL}
};
@@ -303,6 +304,12 @@ static PyObject *make_builtopts_info(void)
SetObjIncref(Py_False);
#endif
+#ifdef WITH_OPENVDB
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
#undef SetObjIncref
return builtopts_info;
diff --git a/source/blender/python/intern/bpy_app_openvdb.c b/source/blender/python/intern/bpy_app_openvdb.c
new file mode 100644
index 00000000000..8a24aaf0555
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_openvdb.c
@@ -0,0 +1,117 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_openvdb.c
+ * \ingroup pythonintern
+ */
+
+#include <Python.h>
+#include "BLI_utildefines.h"
+
+#include "bpy_app_openvdb.h"
+
+#ifdef WITH_OPENVDB
+# include "openvdb_capi.h"
+#endif
+
+static PyTypeObject BlenderAppOVDBType;
+
+static PyStructSequence_Field app_openvdb_info_fields[] = {
+ {(char *)"supported", (char *)("Boolean, True when Blender is built with OpenVDB support")},
+ {(char *)("version"), (char *)("The OpenVDB version as a tuple of 3 numbers")},
+ {(char *)("version_string"), (char *)("The OpenVDB version formatted as a string")},
+ {NULL}
+};
+
+static PyStructSequence_Desc app_openvdb_info_desc = {
+ (char *)"bpy.app.openvdb", /* name */
+ (char *)"This module contains information about OpenVDB blender is linked against", /* doc */
+ app_openvdb_info_fields, /* fields */
+ ARRAY_SIZE(app_openvdb_info_fields) - 1
+};
+
+static PyObject *make_openvdb_info(void)
+{
+ PyObject *openvdb_info;
+ int pos = 0;
+
+#ifdef WITH_OPENVDB
+ int curversion;
+#endif
+
+ openvdb_info = PyStructSequence_New(&BlenderAppOVDBType);
+ if (openvdb_info == NULL) {
+ return NULL;
+ }
+
+#ifndef WITH_OPENVDB
+#define SetStrItem(str) \
+ PyStructSequence_SET_ITEM(openvdb_info, pos++, PyUnicode_FromString(str))
+#endif
+
+#define SetObjItem(obj) \
+ PyStructSequence_SET_ITEM(openvdb_info, pos++, obj)
+
+#ifdef WITH_OPENVDB
+ curversion = OpenVDB_getVersionHex();
+ SetObjItem(PyBool_FromLong(1));
+ SetObjItem(Py_BuildValue("(iii)",
+ curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
+ SetObjItem(PyUnicode_FromFormat("%2d, %2d, %2d",
+ curversion >> 24, (curversion >> 16) % 256, (curversion >> 8) % 256));
+#else
+ SetObjItem(PyBool_FromLong(0));
+ SetObjItem(Py_BuildValue("(iii)", 0, 0, 0));
+ SetStrItem("Unknown");
+#endif
+
+ if (PyErr_Occurred()) {
+ Py_CLEAR(openvdb_info);
+ return NULL;
+ }
+
+#undef SetStrItem
+#undef SetObjItem
+
+ return openvdb_info;
+}
+
+PyObject *BPY_app_openvdb_struct(void)
+{
+ PyObject *ret;
+
+ PyStructSequence_InitType(&BlenderAppOVDBType, &app_openvdb_info_desc);
+
+ ret = make_openvdb_info();
+
+ /* prevent user from creating new instances */
+ BlenderAppOVDBType.tp_init = NULL;
+ BlenderAppOVDBType.tp_new = NULL;
+ BlenderAppOVDBType.tp_hash = (hashfunc)_Py_HashPointer; /* without this we can't do set(sys.modules) [#29635] */
+
+ return ret;
+}
diff --git a/source/blender/python/intern/bpy_app_openvdb.h b/source/blender/python/intern/bpy_app_openvdb.h
new file mode 100644
index 00000000000..12fa54ea7a3
--- /dev/null
+++ b/source/blender/python/intern/bpy_app_openvdb.h
@@ -0,0 +1,38 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Kevin Dietrich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/intern/bpy_app_openvdb.h
+ * \ingroup pythonintern
+ */
+
+#ifndef __BPY_APP_OPENVDB_H__
+#define __BPY_APP_OPENVDB_H__
+
+PyObject *BPY_app_openvdb_struct(void);
+
+#endif /* __BPY_APP_OPENVDB_H__ */
+
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index e8c710e68ae..65432fc3f88 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -218,6 +218,10 @@ endif()
list(APPEND BLENDER_SORTED_LIBS bf_intern_opensubdiv)
endif()
+ if(WITH_OPENVDB)
+ list(APPEND BLENDER_SORTED_LIBS bf_intern_openvdb)
+ endif()
+
foreach(SORTLIB ${BLENDER_SORTED_LIBS})
set(REMLIB ${SORTLIB})
foreach(SEARCHLIB ${BLENDER_LINK_LIBS})