diff options
-rw-r--r-- | intern/cycles/CMakeLists.txt | 11 | ||||
-rw-r--r-- | intern/cycles/app/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/blender/CMakeLists.txt | 14 | ||||
-rw-r--r-- | intern/cycles/blender/blender_geometry.cpp | 7 | ||||
-rw-r--r-- | intern/cycles/blender/blender_object.cpp | 10 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.cpp | 5 | ||||
-rw-r--r-- | intern/cycles/blender/blender_volume.cpp | 140 | ||||
-rw-r--r-- | intern/cycles/render/CMakeLists.txt | 23 | ||||
-rw-r--r-- | intern/cycles/render/image_vdb.cpp | 188 | ||||
-rw-r--r-- | intern/cycles/render/image_vdb.h | 56 | ||||
-rw-r--r-- | intern/cycles/test/CMakeLists.txt | 2 |
11 files changed, 429 insertions, 28 deletions
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 6d4d2e38e82..024a94ea437 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -350,17 +350,6 @@ if(WITH_CYCLES_NETWORK) add_definitions(-DWITH_NETWORK) endif() -if(WITH_OPENCOLORIO) - add_definitions(-DWITH_OCIO) - include_directories( - SYSTEM - ${OPENCOLORIO_INCLUDE_DIRS} - ) - if(WIN32) - add_definitions(-DOpenColorIO_STATIC) - endif() -endif() - if(WITH_CYCLES_STANDALONE OR WITH_CYCLES_NETWORK OR WITH_CYCLES_CUBIN_COMPILER) add_subdirectory(app) endif() diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt index 199ab8ce316..ef374f91a65 100644 --- a/intern/cycles/app/CMakeLists.txt +++ b/intern/cycles/app/CMakeLists.txt @@ -60,6 +60,7 @@ link_directories( ${TIFF_LIBPATH} ${OPENEXR_LIBPATH} ${OPENJPEG_LIBPATH} + ${OPENVDB_LIBPATH} ) if(WITH_OPENCOLORIO) diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index ae191b6c0f7..496e8e9310b 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -92,6 +92,20 @@ if(WITH_MOD_FLUID) add_definitions(-DWITH_FLUID) endif() +if(WITH_NEW_OBJECT_TYPES) + add_definitions(-DWITH_NEW_OBJECT_TYPES) +endif() + +if(WITH_OPENVDB) + add_definitions(-DWITH_OPENVDB ${OPENVDB_DEFINITIONS}) + list(APPEND INC_SYS + ${OPENVDB_INCLUDE_DIRS} + ) + list(APPEND LIB + ${OPENVDB_LIBRARIES} + ) +endif() + blender_add_lib(bf_intern_cycles "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") # avoid link failure with clang 3.4 debug diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp index e2a4a125ca1..ac5bae4bc66 100644 --- a/intern/cycles/blender/blender_geometry.cpp +++ b/intern/cycles/blender/blender_geometry.cpp @@ -38,7 +38,8 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, BL::ID b_key_id = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data; GeometryKey key(b_key_id.ptr.data, use_particle_hair); BL::Material material_override = view_layer.material_override; - Shader *default_shader = scene->default_surface; + Shader *default_shader = (b_ob.type() == BL::Object::type_VOLUME) ? scene->default_volume : + scene->default_surface; Geometry::Type geom_type = (use_particle_hair && (scene->curve_system_manager->primitive != CURVE_TRIANGLES)) ? Geometry::HAIR : @@ -124,7 +125,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, if (use_particle_hair) { sync_hair(b_depsgraph, b_ob, geom, used_shaders); } - else if (object_fluid_gas_domain_find(b_ob)) { + else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) { Mesh *mesh = static_cast<Mesh *>(geom); sync_volume(b_ob, mesh, used_shaders); } @@ -164,7 +165,7 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph, if (use_particle_hair) { sync_hair_motion(b_depsgraph, b_ob, geom, motion_step); } - else if (object_fluid_gas_domain_find(b_ob)) { + else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) { /* No volume motion blur support yet. */ } else { diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 334c25cafe1..48d309c259b 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -67,10 +67,16 @@ bool BlenderSync::object_is_mesh(BL::Object &b_ob) return false; } - if (b_ob.type() == BL::Object::type_CURVE) { + BL::Object::type_enum type = b_ob.type(); + + if (type == BL::Object::type_VOLUME) { + /* Will be exported attached to mesh. */ + return true; + } + else if (type == BL::Object::type_CURVE) { /* Skip exporting curves without faces, overhead can be * significant if there are many for path animation. */ - BL::Curve b_curve(b_ob.data()); + BL::Curve b_curve(b_ob_data); return (b_curve.bevel_object() || b_curve.extrude() != 0.0f || b_curve.bevel_depth() != 0.0f || b_curve.dimensions() == BL::Curve::dimensions_2D || b_ob.modifiers.length()); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 4529c6a2798..3d932825ae7 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -178,6 +178,11 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d world_recalc = true; } } + /* Volume */ + else if (b_id.is_a(&RNA_Volume)) { + BL::Volume b_volume(b_id); + geometry_map.set_recalc(b_volume); + } } BlenderViewportParameters new_viewport_parameters(b_v3d); diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp index 7f393fcb819..ee64796b393 100644 --- a/intern/cycles/blender/blender_volume.cpp +++ b/intern/cycles/blender/blender_volume.cpp @@ -16,12 +16,19 @@ #include "render/colorspace.h" #include "render/image.h" +#include "render/image_vdb.h" #include "render/mesh.h" #include "render/object.h" #include "blender/blender_sync.h" #include "blender/blender_util.h" +#ifdef WITH_OPENVDB +# include <openvdb/openvdb.h> +openvdb::GridBase::ConstPtr BKE_volume_grid_openvdb_for_read(const struct Volume *volume, + struct VolumeGrid *grid); +#endif + CCL_NAMESPACE_BEGIN /* TODO: verify this is not loading unnecessary attributes. */ @@ -210,19 +217,121 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Mesh *mesh, float attr->data_voxel() = scene->image_manager->add_image(loader, params); } +} - /* Create a matrix to transform from object space to mesh texture space. - * This does not work with deformations but that can probably only be done - * well with a volume grid mapping of coordinates. */ - if (mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) { - Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM); - Transform *tfm = attr->data_transform(); +class BlenderVolumeLoader : public VDBImageLoader { + public: + BlenderVolumeLoader(BL::Volume b_volume, const string &grid_name) + : VDBImageLoader(grid_name), + b_volume(b_volume), + b_volume_grid(PointerRNA_NULL), + unload(false) + { +#ifdef WITH_OPENVDB + /* Find grid with matching name. */ + BL::Volume::grids_iterator b_grid_iter; + for (b_volume.grids.begin(b_grid_iter); b_grid_iter != b_volume.grids.end(); ++b_grid_iter) { + if (b_grid_iter->name() == grid_name) { + b_volume_grid = *b_grid_iter; + } + } +#endif + } - BL::Mesh b_mesh(b_ob.data()); - float3 loc, size; - mesh_texture_space(b_mesh, loc, size); + bool load_metadata(ImageMetaData &metadata) override + { + if (!b_volume_grid) { + return false; + } + + unload = !b_volume_grid.is_loaded(); + +#ifdef WITH_OPENVDB + Volume *volume = (Volume *)b_volume.ptr.data; + VolumeGrid *volume_grid = (VolumeGrid *)b_volume_grid.ptr.data; + grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid); +#endif + + return VDBImageLoader::load_metadata(metadata); + } + + bool load_pixels(const ImageMetaData &metadata, + void *pixels, + const size_t pixel_size, + const bool associate_alpha) override + { + if (!b_volume_grid) { + return false; + } + + return VDBImageLoader::load_pixels(metadata, pixels, pixel_size, associate_alpha); + } - *tfm = transform_translate(-loc) * transform_scale(size); + bool equals(const ImageLoader &other) const override + { + /* TODO: detect multiple volume datablocks with the same filepath. */ + const BlenderVolumeLoader &other_loader = (const BlenderVolumeLoader &)other; + return b_volume == other_loader.b_volume && b_volume_grid == other_loader.b_volume_grid; + } + + void cleanup() override + { + VDBImageLoader::cleanup(); + if (b_volume_grid && unload) { + b_volume_grid.unload(); + } + } + + BL::Volume b_volume; + BL::VolumeGrid b_volume_grid; + bool unload; +}; + +static void sync_volume_object(BL::BlendData &b_data, BL::Object &b_ob, Scene *scene, Mesh *mesh) +{ + BL::Volume b_volume(b_ob.data()); + b_volume.grids.load(b_data.ptr.data); + + mesh->volume_isovalue = 1e-3f; /* TODO: make user setting. */ + + /* Find grid with matching name. */ + BL::Volume::grids_iterator b_grid_iter; + for (b_volume.grids.begin(b_grid_iter); b_grid_iter != b_volume.grids.end(); ++b_grid_iter) { + BL::VolumeGrid b_grid = *b_grid_iter; + ustring name = ustring(b_grid.name()); + AttributeStandard std = ATTR_STD_NONE; + + if (name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) { + std = ATTR_STD_VOLUME_DENSITY; + } + else if (name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) { + std = ATTR_STD_VOLUME_COLOR; + } + else if (name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) { + std = ATTR_STD_VOLUME_FLAME; + } + else if (name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) { + std = ATTR_STD_VOLUME_HEAT; + } + else if (name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) { + std = ATTR_STD_VOLUME_TEMPERATURE; + } + else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) { + std = ATTR_STD_VOLUME_VELOCITY; + } + + if ((std != ATTR_STD_NONE && mesh->need_attribute(scene, std)) || + mesh->need_attribute(scene, name)) { + Attribute *attr = (std != ATTR_STD_NONE) ? + mesh->attributes.add(std) : + mesh->attributes.add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL); + + ImageLoader *loader = new BlenderVolumeLoader(b_volume, name.string()); + ImageParams params; + params.frame = b_volume.grids.frame(); + + attr->data_voxel() = scene->image_manager->add_image(loader, params); + } } } @@ -246,9 +355,16 @@ void BlenderSync::sync_volume(BL::Object &b_ob, Mesh *mesh, const vector<Shader mesh->clear(); mesh->used_shaders = used_shaders; - /* Smoke domain. */ if (view_layer.use_volumes) { - sync_smoke_volume(scene, b_ob, mesh, b_scene.frame_current()); + if (b_ob.type() == BL::Object::type_VOLUME) { + /* Volume object. Create only attributes, bounding mesh will then + * be automatically generated later. */ + sync_volume_object(b_data, b_ob, scene, mesh); + } + else { + /* Smoke domain. */ + sync_smoke_volume(scene, b_ob, mesh, b_scene.frame_current()); + } } /* Tag update. */ diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index 9922547a8d2..472b5a0c101 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -24,6 +24,7 @@ set(SRC hair.cpp image.cpp image_oiio.cpp + image_vdb.cpp integrator.cpp jitter.cpp light.cpp @@ -63,6 +64,7 @@ set(SRC_HEADERS hair.h image.h image_oiio.h + image_vdb.h integrator.h light.h jitter.h @@ -98,6 +100,27 @@ if(WITH_CYCLES_OSL) SET_PROPERTY(SOURCE osl.cpp PROPERTY COMPILE_FLAGS ${RTTI_DISABLE_FLAGS}) endif() +if(WITH_OPENCOLORIO) + add_definitions(-DWITH_OCIO) + include_directories( + SYSTEM + ${OPENCOLORIO_INCLUDE_DIRS} + ) + if(WIN32) + add_definitions(-DOpenColorIO_STATIC) + endif() +endif() + +if(WITH_OPENVDB) + add_definitions(-DWITH_OPENVDB ${OPENVDB_DEFINITIONS}) + list(APPEND INC_SYS + ${OPENVDB_INCLUDE_DIRS} + ) + list(APPEND LIB + ${OPENVDB_LIBRARIES} + ) +endif() + include_directories(${INC}) include_directories(SYSTEM ${INC_SYS}) diff --git a/intern/cycles/render/image_vdb.cpp b/intern/cycles/render/image_vdb.cpp new file mode 100644 index 00000000000..500131c2d84 --- /dev/null +++ b/intern/cycles/render/image_vdb.cpp @@ -0,0 +1,188 @@ +/* + * Copyright 2011-2020 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "render/image_vdb.h" + +#ifdef WITH_OPENVDB +# include <openvdb/openvdb.h> +# include <openvdb/tools/Dense.h> +#endif + +CCL_NAMESPACE_BEGIN + +VDBImageLoader::VDBImageLoader(const string &grid_name) : grid_name(grid_name) +{ +} + +VDBImageLoader::~VDBImageLoader() +{ +} + +bool VDBImageLoader::load_metadata(ImageMetaData &metadata) +{ +#ifdef WITH_OPENVDB + if (!grid) { + return false; + } + + bbox = grid->evalActiveVoxelBoundingBox(); + if (bbox.empty()) { + return false; + } + + /* Set dimensions. */ + openvdb::Coord dim = bbox.dim(); + openvdb::Coord min = bbox.min(); + metadata.width = dim.x(); + metadata.height = dim.y(); + metadata.depth = dim.z(); + + /* Set data type. */ + if (grid->isType<openvdb::FloatGrid>()) { + metadata.channels = 1; + } + else if (grid->isType<openvdb::Vec3fGrid>()) { + metadata.channels = 3; + } + else if (grid->isType<openvdb::BoolGrid>()) { + metadata.channels = 1; + } + else if (grid->isType<openvdb::DoubleGrid>()) { + metadata.channels = 1; + } + else if (grid->isType<openvdb::Int32Grid>()) { + metadata.channels = 1; + } + else if (grid->isType<openvdb::Int64Grid>()) { + metadata.channels = 1; + } + else if (grid->isType<openvdb::Vec3IGrid>()) { + metadata.channels = 3; + } + else if (grid->isType<openvdb::Vec3dGrid>()) { + metadata.channels = 3; + } + else if (grid->isType<openvdb::MaskGrid>()) { + metadata.channels = 1; + } + else { + return false; + } + + if (metadata.channels == 1) { + metadata.type = IMAGE_DATA_TYPE_FLOAT; + } + else { + metadata.type = IMAGE_DATA_TYPE_FLOAT4; + } + + /* Set transform from object space to voxel index. */ + openvdb::math::Mat4f grid_matrix = grid->transform().baseMap()->getAffineMap()->getMat4(); + Transform index_to_object; + for (int col = 0; col < 4; col++) { + for (int row = 0; row < 3; row++) { + index_to_object[row][col] = (float)grid_matrix[col][row]; + } + } + + Transform texture_to_index = transform_translate(min.x(), min.y(), min.z()) * + transform_scale(dim.x(), dim.y(), dim.z()); + + metadata.transform_3d = transform_inverse(index_to_object * texture_to_index); + metadata.use_transform_3d = true; + + return true; +#else + (void)metadata; + return false; +#endif +} + +bool VDBImageLoader::load_pixels(const ImageMetaData &, void *pixels, const size_t, const bool) +{ +#ifdef WITH_OPENVDB + if (grid->isType<openvdb::FloatGrid>()) { + openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); + openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid), dense); + } + else if (grid->isType<openvdb::Vec3fGrid>()) { + openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense( + bbox, (openvdb::Vec3f *)pixels); + openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid), dense); + } + else if (grid->isType<openvdb::BoolGrid>()) { + openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); + openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid), dense); + } + else if (grid->isType<openvdb::DoubleGrid>()) { + openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); + openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid), dense); + } + else if (grid->isType<openvdb::Int32Grid>()) { + openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); + openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid), dense); + } + else if (grid->isType<openvdb::Int64Grid>()) { + openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); + openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid), dense); + } + else if (grid->isType<openvdb::Vec3IGrid>()) { + openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense( + bbox, (openvdb::Vec3f *)pixels); + openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid), dense); + } + else if (grid->isType<openvdb::Vec3dGrid>()) { + openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense( + bbox, (openvdb::Vec3f *)pixels); + openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid), dense); + } + else if (grid->isType<openvdb::MaskGrid>()) { + openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels); + openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid), dense); + } + + return true; +#else + (void)pixels; + return false; +#endif +} + +string VDBImageLoader::name() const +{ + return grid_name; +} + +bool VDBImageLoader::equals(const ImageLoader &other) const +{ +#ifdef WITH_OPENVDB + const VDBImageLoader &other_loader = (const VDBImageLoader &)other; + return grid == other_loader.grid; +#else + (void)other; + return true; +#endif +} + +void VDBImageLoader::cleanup() +{ +#ifdef WITH_OPENVDB + /* Free OpenVDB grid memory as soon as we can. */ + grid.reset(); +#endif +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/image_vdb.h b/intern/cycles/render/image_vdb.h new file mode 100644 index 00000000000..7dec63b11e6 --- /dev/null +++ b/intern/cycles/render/image_vdb.h @@ -0,0 +1,56 @@ +/* + * Copyright 2011-2020 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __IMAGE_VDB__ +#define __IMAGE_VDB__ + +#ifdef WITH_OPENVDB +# include <openvdb/openvdb.h> +#endif + +#include "render/image.h" + +CCL_NAMESPACE_BEGIN + +class VDBImageLoader : public ImageLoader { + public: + VDBImageLoader(const string &grid_name); + ~VDBImageLoader(); + + virtual bool load_metadata(ImageMetaData &metadata) override; + + virtual bool load_pixels(const ImageMetaData &metadata, + void *pixels, + const size_t pixels_size, + const bool associate_alpha) override; + + virtual string name() const override; + + virtual bool equals(const ImageLoader &other) const override; + + virtual void cleanup() override; + + protected: + string grid_name; +#ifdef WITH_OPENVDB + openvdb::GridBase::ConstPtr grid; + openvdb::CoordBBox bbox; +#endif +}; + +CCL_NAMESPACE_END + +#endif /* __IMAGE_VDB__ */ diff --git a/intern/cycles/test/CMakeLists.txt b/intern/cycles/test/CMakeLists.txt index ab7a9c75e17..6dcc7f7b3dd 100644 --- a/intern/cycles/test/CMakeLists.txt +++ b/intern/cycles/test/CMakeLists.txt @@ -82,6 +82,7 @@ list(APPEND ALL_CYCLES_LIBRARIES ${TIFF_LIBRARY} ${OPENIMAGEIO_LIBRARIES} ${OPENEXR_LIBRARIES} + ${OPENVDB_LIBRARIES} ) include_directories(${INC}) @@ -95,6 +96,7 @@ link_directories( ${TIFF_LIBPATH} ${OPENEXR_LIBPATH} ${OPENCOLORIO_LIBPATH} + ${OPENVDB_LIBPATH} ) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}") |