WIP: Volume grid attribute support in geometry nodes #110044
|
@ -22,7 +22,6 @@ namespace blender::bke {
|
|||
|
||||
class CurvesGeometry;
|
||||
class GeometryFieldInput;
|
||||
// class VolumeGeometry;
|
||||
|
||||
class MeshFieldContext : public fn::FieldContext {
|
||||
private:
|
||||
|
|
|
@ -139,556 +139,4 @@ struct GAttributeGridWriter {
|
|||
}
|
||||
};
|
||||
|
||||
/* OLD CODE
|
||||
* OLD CODE
|
||||
* OLD CODE
|
||||
* OLD CODE
|
||||
* OLD CODE */
|
||||
|
||||
#if 0
|
||||
|
||||
# ifdef WITH_OPENVDB
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename Fn> struct TypeTagExecutor {
|
||||
const Fn &fn;
|
||||
|
||||
template<typename T> void operator()() const
|
||||
{
|
||||
fn(TypeTag<T>{});
|
||||
}
|
||||
|
||||
void operator()() const
|
||||
{
|
||||
fn(TypeTag<void>{});
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Call operator for static type of the form:
|
||||
* void MyOperator<GridType>();
|
||||
*
|
||||
* e.g.
|
||||
* void MyOperator<openvdb::FloatGrid>();
|
||||
* void MyOperator<openvdb::Vec3fGrid>();
|
||||
*/
|
||||
template<typename Fn> auto volume_grid_to_static_type(const VolumeGridType grid_type, Fn &&fn)
|
||||
{
|
||||
switch (grid_type) {
|
||||
case VOLUME_GRID_FLOAT:
|
||||
return fn.template operator()<openvdb::FloatGrid>();
|
||||
case VOLUME_GRID_VECTOR_FLOAT:
|
||||
return fn.template operator()<openvdb::Vec3fGrid>();
|
||||
case VOLUME_GRID_BOOLEAN:
|
||||
return fn.template operator()<openvdb::BoolGrid>();
|
||||
case VOLUME_GRID_DOUBLE:
|
||||
return fn.template operator()<openvdb::DoubleGrid>();
|
||||
case VOLUME_GRID_INT:
|
||||
return fn.template operator()<openvdb::Int32Grid>();
|
||||
case VOLUME_GRID_INT64:
|
||||
return fn.template operator()<openvdb::Int64Grid>();
|
||||
case VOLUME_GRID_VECTOR_INT:
|
||||
return fn.template operator()<openvdb::Vec3IGrid>();
|
||||
case VOLUME_GRID_VECTOR_DOUBLE:
|
||||
return fn.template operator()<openvdb::Vec3dGrid>();
|
||||
case VOLUME_GRID_MASK:
|
||||
// return fn.template operator()<openvdb::MaskGrid>();
|
||||
break;
|
||||
case VOLUME_GRID_POINTS:
|
||||
// return fn.template operator()<openvdb::points::PointDataGrid>();
|
||||
break;
|
||||
case VOLUME_GRID_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Should never be called. */
|
||||
BLI_assert_msg(0, "should never be reached");
|
||||
return fn.template operator()<openvdb::FloatGrid>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call operator for static type with a dummy tag instance
|
||||
* (easier to use with lambdas), e.g :
|
||||
* void MyOperator(TypeTag<GridType> dummy);
|
||||
*
|
||||
* e.g.
|
||||
* void MyOperator(TypeTag<openvdb::FloatGrid>);
|
||||
* void MyOperator(TypeTag<openvdb::Vec3fGrid>);
|
||||
*/
|
||||
template<typename Fn> auto volume_grid_to_static_type_tag(const VolumeGridType grid_type, Fn &&fn)
|
||||
{
|
||||
detail::TypeTagExecutor<Fn> executor{fn};
|
||||
return volume_grid_to_static_type(grid_type, executor);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Grid Value Converter
|
||||
* \{ */
|
||||
|
||||
template<typename GridValueT> struct GridValueConverter {
|
||||
using GridValueType = GridValueT;
|
||||
using AttributeType = GridValueT;
|
||||
|
||||
static AttributeType to_attribute(const GridValueType &value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
static GridValueType to_grid(const AttributeType &value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct GridValueConverter<double> {
|
||||
using GridValueType = double;
|
||||
using AttributeType = float;
|
||||
|
||||
static AttributeType to_attribute(const GridValueType &value)
|
||||
{
|
||||
return double(value);
|
||||
}
|
||||
static GridValueType to_grid(const AttributeType &value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct GridValueConverter<openvdb::Vec3d> {
|
||||
using GridValueType = openvdb::Vec3d;
|
||||
using AttributeType = blender::float3;
|
||||
|
||||
static AttributeType to_attribute(const GridValueType &value)
|
||||
{
|
||||
return float3(float(value.x()), float(value.y()), float(value.z()));
|
||||
}
|
||||
static GridValueType to_grid(const AttributeType &value)
|
||||
{
|
||||
return openvdb::Vec3d(value.x, value.y, value.z);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct GridValueConverter<openvdb::Vec3i> {
|
||||
using GridValueType = openvdb::Vec3i;
|
||||
using AttributeType = blender::float3;
|
||||
|
||||
static AttributeType to_attribute(const GridValueType &value)
|
||||
{
|
||||
return float3(float(value.x()), float(value.y()), float(value.z()));
|
||||
}
|
||||
static GridValueType to_grid(const AttributeType &value)
|
||||
{
|
||||
return openvdb::Vec3i(int(value.x), int(value.y), int(value.z));
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct GridValueConverter<openvdb::Vec3f> {
|
||||
using GridValueType = openvdb::Vec3f;
|
||||
using AttributeType = blender::float3;
|
||||
|
||||
static AttributeType to_attribute(const GridValueType &value)
|
||||
{
|
||||
return float3(value.x(), value.y(), value.z());
|
||||
}
|
||||
static GridValueType to_grid(const AttributeType &value)
|
||||
{
|
||||
return openvdb::Vec3f(value.x, value.y, value.z);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct GridValueConverter<openvdb::PointDataIndex32> {
|
||||
using GridValueType = openvdb::PointDataIndex32;
|
||||
using AttributeType = int32_t;
|
||||
|
||||
static AttributeType to_attribute(const GridValueType &value)
|
||||
{
|
||||
return int32_t(value);
|
||||
}
|
||||
static GridValueType to_grid(const AttributeType &value)
|
||||
{
|
||||
return GridValueType(value);
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
template<template<typename> typename VArrayImplT>
|
||||
GVArray get_volume_varray(const openvdb::GridBase &vdb_grid, VolumeGridType grid_type)
|
||||
{
|
||||
GVArray result;
|
||||
volume_grid_to_static_type_tag(grid_type, [&](auto tag) {
|
||||
using GridType = typename decltype(tag)::type;
|
||||
using VArrayImplType = VArrayImplT<GridType>;
|
||||
using AttributeType = typename VArrayImplType::AttributeType;
|
||||
|
||||
result = VArray<AttributeType>::template For<VArrayImplType>(
|
||||
static_cast<const GridType &>(vdb_grid));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
template<template<typename> typename VArrayImplT>
|
||||
GVArray get_volume_varray(const VolumeGridVector &grids,
|
||||
const AttributeIDRef &attribute_id,
|
||||
bool use_first_grid)
|
||||
{
|
||||
if (grids.empty()) {
|
||||
return {};
|
||||
}
|
||||
const VolumeGrid *grid = use_first_grid ? (grids.empty() ? nullptr : &grids.front()) :
|
||||
grids.find_grid(attribute_id);
|
||||
if (grid == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return get_volume_varray<VArrayImplT>(*grid->grid(), grid->grid_type());
|
||||
}
|
||||
|
||||
template<template<typename> typename VArrayImplT>
|
||||
GVMutableArray get_volume_vmutablearray(openvdb::GridBase &vdb_grid, VolumeGridType grid_type)
|
||||
{
|
||||
GVMutableArray result;
|
||||
volume_grid_to_static_type_tag(grid_type, [&](auto tag) {
|
||||
using GridType = typename decltype(tag)::type;
|
||||
using VArrayImplType = VArrayImplT<GridType>;
|
||||
using AttributeType = typename VArrayImplType::AttributeType;
|
||||
|
||||
result = VMutableArray<AttributeType>::template For<VArrayImplType>(
|
||||
static_cast<const GridType &>(vdb_grid));
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
template<template<typename> typename VArrayImplT>
|
||||
GVMutableArray get_volume_vmutablearray(VolumeGridVector &grids,
|
||||
const AttributeIDRef &attribute_id)
|
||||
{
|
||||
if (grids.empty()) {
|
||||
return {};
|
||||
}
|
||||
VolumeGrid *grid = grids.find_grid(attribute_id);
|
||||
if (grid == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return get_volume_vmutablearray<VArrayImplT>(*grid->grid(), grid->grid_type());
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name CPP Type for grid type
|
||||
* \{ */
|
||||
|
||||
inline const CPPType &volume_grid_type_to_cpp_type(const VolumeGridType grid_type)
|
||||
{
|
||||
const CPPType *cpptype = nullptr;
|
||||
volume_grid_to_static_type_tag(grid_type, [&cpptype](auto tag) {
|
||||
using GridType = typename decltype(tag)::type;
|
||||
using Converter = typename bke::template GridValueConverter<typename GridType::ValueType>;
|
||||
using AttributeType = typename Converter::AttributeType;
|
||||
cpptype = &CPPType::get<AttributeType>();
|
||||
});
|
||||
return *cpptype;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Grid Value Virtual Array
|
||||
* \{ */
|
||||
|
||||
template<typename _GridType>
|
||||
class VArrayImpl_For_VolumeGridValue final
|
||||
: public VMutableArrayImpl<
|
||||
typename bke::GridValueConverter<typename _GridType::ValueType>::AttributeType> {
|
||||
public:
|
||||
using GridType = typename std::remove_cv<_GridType>::type;
|
||||
using TreeType = typename GridType::TreeType;
|
||||
using ValueType = typename GridType::ValueType;
|
||||
using Converter = bke::GridValueConverter<ValueType>;
|
||||
using AttributeType = typename Converter::AttributeType;
|
||||
using LeafNodeType = typename TreeType::LeafNodeType;
|
||||
using LeafManager = openvdb::tree::LeafManager<TreeType>;
|
||||
using LeafRange = typename LeafManager::LeafRange;
|
||||
using BufferType = typename LeafManager::BufferType;
|
||||
|
||||
protected:
|
||||
GridType &grid_;
|
||||
LeafManager leaf_manager_;
|
||||
/* Offset indices for leaf node buffers. */
|
||||
/* XXX this should be shared between VArrays accessing the same grid. */
|
||||
Array<size_t> prefix_sum_;
|
||||
|
||||
public:
|
||||
VArrayImpl_For_VolumeGridValue(GridType &grid)
|
||||
: VMutableArrayImpl<AttributeType>(grid.activeVoxelCount()),
|
||||
grid_(grid),
|
||||
leaf_manager_(*grid_.treePtr()),
|
||||
prefix_sum_(leaf_manager_.leafCount())
|
||||
{
|
||||
size_t *prefix_data = prefix_sum_.data();
|
||||
size_t prefix_size = prefix_sum_.size();
|
||||
leaf_manager_.getPrefixSum(prefix_data, prefix_size);
|
||||
}
|
||||
|
||||
VArrayImpl_For_VolumeGridValue(const GridType &grid)
|
||||
: VMutableArrayImpl<AttributeType>(grid.activeVoxelCount()),
|
||||
grid_(const_cast<GridType &>(grid)),
|
||||
leaf_manager_(*grid_.treePtr()),
|
||||
prefix_sum_(leaf_manager_.leafCount())
|
||||
{
|
||||
size_t *prefix_data = prefix_sum_.data();
|
||||
size_t prefix_size = prefix_sum_.size();
|
||||
leaf_manager_.getPrefixSum(prefix_data, prefix_size);
|
||||
}
|
||||
|
||||
AttributeType get(const int64_t index) const override
|
||||
{
|
||||
/**
|
||||
* TODO Index-based access is very inefficient for leaf node buffers,
|
||||
* since linear search through active voxels is needed per leaf.
|
||||
* Implement all available alternative access methods to avoid
|
||||
* this as much as possible.
|
||||
*/
|
||||
const size_t *buffer_index_ptr = std::upper_bound(
|
||||
prefix_sum_.begin(), prefix_sum_.end(), index) -
|
||||
1;
|
||||
const size_t leaf_index = buffer_index_ptr - prefix_sum_.begin();
|
||||
BLI_assert(IndexRange(leaf_manager_.leafCount()).contains(leaf_index));
|
||||
const LeafNodeType &leaf = leaf_manager_.leaf(leaf_index);
|
||||
int64_t i = *buffer_index_ptr;
|
||||
for (typename LeafNodeType::ValueOnCIter iter = leaf.cbeginValueOn(); iter; ++iter, ++i) {
|
||||
if (i == index) {
|
||||
return Converter::to_attribute(iter.getValue());
|
||||
}
|
||||
}
|
||||
return AttributeType{0};
|
||||
}
|
||||
|
||||
void set(const int64_t index, const AttributeType value) override
|
||||
{
|
||||
/**
|
||||
* TODO Index-based access is very inefficient for leaf node buffers,
|
||||
* since linear search through active voxels is needed per leaf.
|
||||
* Implement all available alternative access methods to avoid
|
||||
* this as much as possible.
|
||||
*/
|
||||
const size_t *buffer_index_ptr = std::upper_bound(
|
||||
prefix_sum_.begin(), prefix_sum_.end(), index) -
|
||||
1;
|
||||
const size_t leaf_index = buffer_index_ptr - prefix_sum_.begin();
|
||||
BLI_assert(IndexRange(leaf_manager_.leafCount()).contains(leaf_index));
|
||||
LeafNodeType &leaf = leaf_manager_.leaf(leaf_index);
|
||||
int64_t i = *buffer_index_ptr;
|
||||
for (typename LeafNodeType::ValueOnIter iter = leaf.beginValueOn(); iter; ++iter, ++i) {
|
||||
if (i == index) {
|
||||
iter.setValue(Converter::to_grid(value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_all(Span<AttributeType> src) override
|
||||
{
|
||||
tbb::parallel_for(leaf_manager_.leafRange(), [&](const LeafRange &range) {
|
||||
for (auto leaf_iter = range.begin(); leaf_iter; ++leaf_iter) {
|
||||
const size_t leaf_index = leaf_iter.pos();
|
||||
const IndexRange leaf_buffer_range(prefix_sum_[leaf_index], leaf_iter->onVoxelCount());
|
||||
// std::cout << "Leaf range: " << leaf_buffer_range.start() << " + "
|
||||
// << leaf_buffer_range.size() << std::endl;
|
||||
|
||||
auto iter = leaf_iter->beginValueOn();
|
||||
for (const int src_i : leaf_buffer_range) {
|
||||
iter.setValue(Converter::to_grid(src[src_i]));
|
||||
// std::cout << " set [" << src_i << "] = " << Converter::to_grid(src[src_i]) <<
|
||||
// std::endl;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void materialize(const IndexMask &mask, AttributeType *dst) const override
|
||||
{
|
||||
LeafManager leaf_mgr(*grid_.treePtr());
|
||||
|
||||
/* Offset indices for leaf node buffers. */
|
||||
Array<size_t> prefix_sum(leaf_mgr.activeLeafVoxelCount());
|
||||
size_t *prefix_sum_data = prefix_sum.data();
|
||||
size_t prefix_sum_size = prefix_sum.size();
|
||||
leaf_mgr.getPrefixSum(prefix_sum_data, prefix_sum_size);
|
||||
|
||||
const LeafRange leaf_range = leaf_mgr.leafRange();
|
||||
// int64_t segment_start = 0;
|
||||
// int64_t leaf_start = 0;
|
||||
// for (const int64_t segment_i : IndexRange(segments_num_)) {
|
||||
// const IndexMaskSegment segment = mask->segment(segment_i);
|
||||
mask.foreach_range([&](IndexRange segment, const int64_t segment_pos) {
|
||||
if (segment.is_empty()) {
|
||||
return;
|
||||
}
|
||||
threading::parallel_for(segment, 4096, [&](const IndexRange range) {
|
||||
const int leaf_begin = *std::lower_bound(
|
||||
prefix_sum.begin(), prefix_sum.end(), segment.first());
|
||||
const int leaf_end = *std::upper_bound(
|
||||
prefix_sum.begin(), prefix_sum.end(), segment.last());
|
||||
tbb::parallel_for(leaf_range, [&](const LeafRange &leaf_range) {
|
||||
UNUSED_VARS(dst, leaf_begin, leaf_end, segment_pos, range, leaf_range);
|
||||
// for (auto leaf_iter = range.begin(); leaf_iter; ++leaf_iter) {
|
||||
// const size_t leaf_index = leaf_iter.pos();
|
||||
// const IndexRange leaf_buffer_range(prefix_sum[leaf_index],
|
||||
// leaf_iter->onVoxelCount());
|
||||
|
||||
// auto iter = leaf_iter->beginValueOn();
|
||||
// for (const int src_i : leaf_buffer_range) {
|
||||
// iter.setValue(Converter::to_grid(src[src_i]));
|
||||
// }
|
||||
//}
|
||||
});
|
||||
|
||||
// segment_start += segment.size();
|
||||
});
|
||||
});
|
||||
|
||||
// mask.foreach_index(GrainSize(4096), [&](const int64_t i) {
|
||||
// if (const MDeformWeight *weight = this->find_weight_at_index(i)) {
|
||||
// dst[i] = weight->weight;
|
||||
// }
|
||||
// else {
|
||||
// dst[i] = 0.0f;
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized(const IndexMask &mask, AttributeType *dst) const override
|
||||
{
|
||||
this->materialize(mask, dst);
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Grid Position Virtual Array
|
||||
* \{ */
|
||||
|
||||
template<typename _GridType>
|
||||
class VArrayImpl_For_VolumeGridPosition final : public VArrayImpl<float3> {
|
||||
public:
|
||||
using AttributeType = float3;
|
||||
using Converter = bke::GridValueConverter<openvdb::Vec3d>;
|
||||
using GridType = typename std::remove_cv<_GridType>::type;
|
||||
using TreeType = typename GridType::TreeType;
|
||||
using LeafNodeType = typename TreeType::LeafNodeType;
|
||||
using LeafManager = openvdb::tree::LeafManager<TreeType>;
|
||||
using LeafRange = typename LeafManager::LeafRange;
|
||||
|
||||
protected:
|
||||
GridType &grid_;
|
||||
LeafManager leaf_manager_;
|
||||
/* Offset indices for leaf node buffers. */
|
||||
/* XXX this should be shared between VArrays accessing the same grid. */
|
||||
Array<size_t> prefix_sum_;
|
||||
|
||||
public:
|
||||
VArrayImpl_For_VolumeGridPosition(const GridType &grid)
|
||||
: VArrayImpl<float3>(grid.activeVoxelCount()),
|
||||
grid_(const_cast<GridType &>(grid)),
|
||||
leaf_manager_(*grid_.treePtr()),
|
||||
prefix_sum_(leaf_manager_.leafCount())
|
||||
{
|
||||
size_t *prefix_data = prefix_sum_.data();
|
||||
size_t prefix_size = prefix_sum_.size();
|
||||
leaf_manager_.getPrefixSum(prefix_data, prefix_size);
|
||||
}
|
||||
|
||||
float3 get(const int64_t index) const override
|
||||
{
|
||||
/**
|
||||
* TODO Index-based access is very inefficient for leaf node buffers,
|
||||
* since linear search through active voxels is needed per leaf.
|
||||
* Implement all available alternative access methods to avoid
|
||||
* this as much as possible.
|
||||
*/
|
||||
const size_t *buffer_index_ptr = std::upper_bound(
|
||||
prefix_sum_.begin(), prefix_sum_.end(), index) -
|
||||
1;
|
||||
const size_t leaf_index = buffer_index_ptr - prefix_sum_.begin();
|
||||
BLI_assert(IndexRange(leaf_manager_.leafCount()).contains(leaf_index));
|
||||
const LeafNodeType &leaf = leaf_manager_.leaf(leaf_index);
|
||||
int64_t i = *buffer_index_ptr;
|
||||
for (typename LeafNodeType::ValueOnCIter iter = leaf.cbeginValueOn(); iter; ++iter, ++i) {
|
||||
if (i == index) {
|
||||
return Converter::to_attribute(grid_.indexToWorld(iter.getCoord()));
|
||||
}
|
||||
}
|
||||
return AttributeType{0};
|
||||
}
|
||||
|
||||
void materialize(const IndexMask &mask, float3 *dst) const override
|
||||
{
|
||||
LeafManager leaf_mgr(*grid_.treePtr());
|
||||
|
||||
/* Offset indices for leaf node buffers. */
|
||||
Array<size_t> prefix_sum(leaf_mgr.activeLeafVoxelCount());
|
||||
size_t *prefix_sum_data = prefix_sum.data();
|
||||
size_t prefix_sum_size = prefix_sum.size();
|
||||
leaf_mgr.getPrefixSum(prefix_sum_data, prefix_sum_size);
|
||||
|
||||
const LeafRange leaf_range = leaf_mgr.leafRange();
|
||||
// int64_t segment_start = 0;
|
||||
// int64_t leaf_start = 0;
|
||||
// for (const int64_t segment_i : IndexRange(segments_num_)) {
|
||||
// const IndexMaskSegment segment = mask->segment(segment_i);
|
||||
mask.foreach_range([&](IndexRange segment, const int64_t segment_pos) {
|
||||
if (segment.is_empty()) {
|
||||
return;
|
||||
}
|
||||
threading::parallel_for(segment, 4096, [&](const IndexRange range) {
|
||||
const int leaf_begin = *std::lower_bound(
|
||||
prefix_sum.begin(), prefix_sum.end(), segment.first());
|
||||
const int leaf_end = *std::upper_bound(
|
||||
prefix_sum.begin(), prefix_sum.end(), segment.last());
|
||||
tbb::parallel_for(leaf_range, [&](const LeafRange &leaf_range) {
|
||||
UNUSED_VARS(dst, leaf_begin, leaf_end, segment_pos, range, leaf_range);
|
||||
// for (auto leaf_iter = range.begin(); leaf_iter; ++leaf_iter) {
|
||||
// const size_t leaf_index = leaf_iter.pos();
|
||||
// const IndexRange leaf_buffer_range(prefix_sum[leaf_index],
|
||||
// leaf_iter->onVoxelCount());
|
||||
|
||||
// auto iter = leaf_iter->beginValueOn();
|
||||
// for (const int src_i : leaf_buffer_range) {
|
||||
// iter.setValue(Converter::to_grid(src[src_i]));
|
||||
// }
|
||||
//}
|
||||
});
|
||||
|
||||
// segment_start += segment.size();
|
||||
});
|
||||
});
|
||||
|
||||
// mask.foreach_index(GrainSize(4096), [&](const int64_t i) {
|
||||
// if (const MDeformWeight *weight = this->find_weight_at_index(i)) {
|
||||
// dst[i] = weight->weight;
|
||||
// }
|
||||
// else {
|
||||
// dst[i] = 0.0f;
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
void materialize_to_uninitialized(const IndexMask &mask, float3 *dst) const override
|
||||
{
|
||||
this->materialize(mask, dst);
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DNA_volume_types.h"
|
||||
|
||||
#include "BLI_bounds_types.hh"
|
||||
#include "BLI_generic_virtual_array.hh"
|
||||
#include "BLI_index_mask.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_virtual_array.hh"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_volume.h"
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
* \brief Volume data-block.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
# if 0
|
||||
/**
|
||||
* A C++ class that wraps the DNA struct for better encapsulation and ease of use. It inherits
|
||||
* directly from the struct rather than storing a pointer to avoid more complicated ownership
|
||||
* handling.
|
||||
*/
|
||||
class VolumeGeometry : public ::VolumeGeometry {
|
||||
public:
|
||||
VolumeGeometry();
|
||||
VolumeGeometry(const VolumeGeometry &other);
|
||||
VolumeGeometry(VolumeGeometry &&other);
|
||||
VolumeGeometry &operator=(const VolumeGeometry &other);
|
||||
VolumeGeometry &operator=(VolumeGeometry &&other);
|
||||
~VolumeGeometry();
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Accessors.
|
||||
*/
|
||||
|
||||
int domain_size(eAttrDomain domain) const;
|
||||
|
||||
/**
|
||||
* The largest and smallest position values of evaluated points.
|
||||
*/
|
||||
std::optional<Bounds<float3>> bounds_min_max() const;
|
||||
|
||||
# ifdef WITH_OPENVDB
|
||||
void set_grid(const openvdb::GridBase::Ptr &grid_ptr);
|
||||
# endif
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Operations.
|
||||
*/
|
||||
|
||||
public:
|
||||
/** Call after operations changing the grid tree topology. */
|
||||
void tag_tree_changed();
|
||||
|
||||
AttributeAccessor attributes() const;
|
||||
MutableAttributeAccessor attributes_for_write();
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Attributes.
|
||||
*/
|
||||
|
||||
GVArray adapt_domain(const GVArray &varray, eAttrDomain from, eAttrDomain to) const;
|
||||
template<typename T>
|
||||
VArray<T> adapt_domain(const VArray<T> &varray, eAttrDomain from, eAttrDomain to) const
|
||||
{
|
||||
return this->adapt_domain(GVArray(varray), from, to).typed<T>();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* File Read/Write.
|
||||
*/
|
||||
|
||||
void blend_read_data(BlendDataReader &reader);
|
||||
void blend_write(BlendWriter &writer, ID &id);
|
||||
};
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
inline blender::bke::VolumeGeometry &VolumeGeometry::wrap()
|
||||
{
|
||||
return *reinterpret_cast<blender::bke::VolumeGeometry *>(this);
|
||||
}
|
||||
inline const blender::bke::VolumeGeometry &VolumeGeometry::wrap() const
|
||||
{
|
||||
return *reinterpret_cast<const blender::bke::VolumeGeometry *>(this);
|
||||
}
|
||||
# endif
|
||||
#endif
|
|
@ -311,7 +311,6 @@ set(SRC
|
|||
intern/viewer_path.cc
|
||||
intern/volume.cc
|
||||
intern/volume_attribute.cc
|
||||
intern/volume_geometry.cc
|
||||
intern/volume_grids.cc
|
||||
intern/volume_render.cc
|
||||
intern/volume_to_mesh.cc
|
||||
|
@ -511,7 +510,6 @@ set(SRC
|
|||
BKE_volume.h
|
||||
BKE_volume_attribute.hh
|
||||
BKE_volume_fields.hh
|
||||
BKE_volume_geometry.hh
|
||||
BKE_volume_openvdb.hh
|
||||
BKE_volume_render.h
|
||||
BKE_volume_to_mesh.hh
|
||||
|
|
|
@ -309,412 +309,3 @@ bool VolumeCustomAttributeGridProvider::foreach_attribute(
|
|||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
#if 0
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Volume Geometry Grid
|
||||
* \{ */
|
||||
|
||||
VolumeGeometryGrid::VolumeGeometryGrid() : grid_(nullptr) {}
|
||||
VolumeGeometryGrid::~VolumeGeometryGrid() {}
|
||||
|
||||
VolumeGridType VolumeGeometryGrid::type() const
|
||||
{
|
||||
if (grid_ == nullptr) {
|
||||
return VOLUME_GRID_UNKNOWN;
|
||||
}
|
||||
|
||||
if (grid_->isType<openvdb::FloatGrid>()) {
|
||||
return VOLUME_GRID_FLOAT;
|
||||
}
|
||||
if (grid_->isType<openvdb::Vec3fGrid>()) {
|
||||
return VOLUME_GRID_VECTOR_FLOAT;
|
||||
}
|
||||
if (grid_->isType<openvdb::BoolGrid>()) {
|
||||
return VOLUME_GRID_BOOLEAN;
|
||||
}
|
||||
if (grid_->isType<openvdb::DoubleGrid>()) {
|
||||
return VOLUME_GRID_DOUBLE;
|
||||
}
|
||||
if (grid_->isType<openvdb::Int32Grid>()) {
|
||||
return VOLUME_GRID_INT;
|
||||
}
|
||||
if (grid_->isType<openvdb::Int64Grid>()) {
|
||||
return VOLUME_GRID_INT64;
|
||||
}
|
||||
if (grid_->isType<openvdb::Vec3IGrid>()) {
|
||||
return VOLUME_GRID_VECTOR_INT;
|
||||
}
|
||||
if (grid_->isType<openvdb::Vec3dGrid>()) {
|
||||
return VOLUME_GRID_VECTOR_DOUBLE;
|
||||
}
|
||||
if (grid_->isType<openvdb::MaskGrid>()) {
|
||||
return VOLUME_GRID_MASK;
|
||||
}
|
||||
if (grid_->isType<openvdb::points::PointDataGrid>()) {
|
||||
return VOLUME_GRID_POINTS;
|
||||
}
|
||||
return VOLUME_GRID_UNKNOWN;
|
||||
}
|
||||
|
||||
int64_t VolumeGeometryGrid::active_voxel_num() const
|
||||
{
|
||||
# ifdef WITH_OPENVDB
|
||||
return grid_->activeVoxelCount();
|
||||
# else
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
/** \} */
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
||||
# ifdef WITH_OPENVDB
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Attribute Provider Declaration
|
||||
* \{ */
|
||||
|
||||
// GAttributeReader VolumeGridValueAttributeProvider::try_get_for_read(const void *owner) const
|
||||
//{
|
||||
// // const VolumeGeometryGrid &grid = grid_access_.get_const_grid(owner);
|
||||
// const VolumeGridVector &grids = grid_access_.get_const_grids(owner);
|
||||
// GVArray varray = get_volume_varray<VArrayImpl_For_VolumeGridValue>(grids);
|
||||
// return {varray, domain_, nullptr};
|
||||
// }
|
||||
//
|
||||
// GAttributeWriter VolumeGridValueAttributeProvider::try_get_for_write(void *owner) const
|
||||
//{
|
||||
// // VolumeGeometryGrid &grid = grid_access_.get_grid(owner);
|
||||
// VolumeGridVector &grids = grid_access_.get_grids(owner);
|
||||
// GVMutableArray varray = get_volume_vmutablearray<VArrayImpl_For_VolumeGridValue>(grids);
|
||||
// return {varray, domain_, nullptr};
|
||||
// }
|
||||
//
|
||||
// bool VolumeGridValueAttributeProvider::try_delete(void * /*owner*/) const
|
||||
//{
|
||||
// if (deletable_ != Deletable) {
|
||||
// return false;
|
||||
// }
|
||||
// /* Not supported. */
|
||||
// // VolumeGeometryGrid &grid = grid_access_.get_grid(owner);
|
||||
// // if (grid.remove_attribute(???)) {
|
||||
// // if (update_on_change_ != nullptr) {
|
||||
// // update_on_change_(owner);
|
||||
// // }
|
||||
// // }
|
||||
// // return true;
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// bool VolumeGridValueAttributeProvider::try_create(void * /*owner*/,
|
||||
// const AttributeInit & /*initializer*/) const
|
||||
//{
|
||||
// if (createable_ != Creatable) {
|
||||
// return false;
|
||||
// }
|
||||
// /* Not supported. */
|
||||
// // VolumeGeometryGrid &grid = grid_access_.get_grid(owner);
|
||||
// // if (grid.add_attribute(???)) {
|
||||
// // if (update_on_change_ != nullptr) {
|
||||
// // update_on_change_(owner);
|
||||
// // }
|
||||
// // return true;
|
||||
// // }
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// bool VolumeGridValueAttributeProvider::exists(const void * /*owner*/) const
|
||||
//{
|
||||
// return true;
|
||||
// }
|
||||
|
||||
GAttributeReader VolumeGridPositionAttributeProvider::try_get_for_read(const void *owner) const
|
||||
{
|
||||
const VolumeGridVector &grids = grid_access_.get_const_grids(owner);
|
||||
GVArray varray = get_volume_varray<VArrayImpl_For_VolumeGridPosition>(
|
||||
grids, AttributeIDRef{"position"}, true);
|
||||
return {varray, domain_, nullptr};
|
||||
}
|
||||
|
||||
GAttributeWriter VolumeGridPositionAttributeProvider::try_get_for_write(void * /*owner*/) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
bool VolumeGridPositionAttributeProvider::try_delete(void * /*owner*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VolumeGridPositionAttributeProvider::try_create(void * /*owner*/,
|
||||
const AttributeInit & /*initializer*/) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VolumeGridPositionAttributeProvider::exists(const void * /*owner*/) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
GAttributeReader VolumeCustomAttributeProvider::try_get_for_read(
|
||||
const void *owner, const AttributeIDRef &attribute_id) const
|
||||
{
|
||||
const VolumeGridVector &grids = grid_access_.get_const_grids(owner);
|
||||
GVArray varray = get_volume_varray<VArrayImpl_For_VolumeGridValue>(grids, attribute_id, false);
|
||||
return {varray, domain_, nullptr};
|
||||
}
|
||||
|
||||
GAttributeWriter VolumeCustomAttributeProvider::try_get_for_write(
|
||||
void *owner, const AttributeIDRef &attribute_id) const
|
||||
{
|
||||
VolumeGridVector &grids = grid_access_.get_grids(owner);
|
||||
GVMutableArray varray = get_volume_vmutablearray<VArrayImpl_For_VolumeGridValue>(grids,
|
||||
attribute_id);
|
||||
return {varray, domain_, nullptr};
|
||||
}
|
||||
|
||||
bool VolumeCustomAttributeProvider::try_delete(void *owner,
|
||||
const AttributeIDRef &attribute_id) const
|
||||
{
|
||||
if (!attribute_id) {
|
||||
return false;
|
||||
}
|
||||
VolumeGridVector &grids = grid_access_.get_grids(owner);
|
||||
bool result = false;
|
||||
grids.remove_if([attribute_id, &result](VolumeGrid &grid) {
|
||||
result = true;
|
||||
return grid.name() == attribute_id.name();
|
||||
});
|
||||
if (result && update_on_change_ != nullptr) {
|
||||
update_on_change_(owner);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static VolumeGridType grid_type_for_custom_data_type(const eCustomDataType data_type)
|
||||
{
|
||||
switch (data_type) {
|
||||
case CD_PROP_FLOAT:
|
||||
return VOLUME_GRID_FLOAT;
|
||||
// case CD_PROP_FLOAT2: return
|
||||
case CD_PROP_FLOAT3:
|
||||
return VOLUME_GRID_VECTOR_FLOAT;
|
||||
case CD_PROP_INT32:
|
||||
return VOLUME_GRID_INT;
|
||||
// case CD_PROP_INT32_2D: return
|
||||
// case CD_PROP_COLOR: return
|
||||
case CD_PROP_BOOL:
|
||||
return VOLUME_GRID_BOOLEAN;
|
||||
// case CD_PROP_INT8: return
|
||||
// case CD_PROP_BYTE_COLOR: return
|
||||
// case CD_PROP_QUATERNION: return
|
||||
// case CD_PROP_STRING: return
|
||||
default:
|
||||
return VOLUME_GRID_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static eCustomDataType custom_data_type_for_grid_type(const VolumeGridType grid_type)
|
||||
{
|
||||
switch (grid_type) {
|
||||
case VOLUME_GRID_FLOAT:
|
||||
return CD_PROP_FLOAT;
|
||||
case VOLUME_GRID_VECTOR_FLOAT:
|
||||
return CD_PROP_FLOAT3;
|
||||
case VOLUME_GRID_INT:
|
||||
return CD_PROP_INT32;
|
||||
case VOLUME_GRID_BOOLEAN:
|
||||
return CD_PROP_BOOL;
|
||||
default:
|
||||
return CD_NUMTYPES;
|
||||
}
|
||||
}
|
||||
|
||||
static openvdb::GridBase::Ptr add_generic_grid(VolumeGridVector &grids,
|
||||
const VolumeGridType grid_type,
|
||||
const eCDAllocType /*alloctype*/,
|
||||
const openvdb::GridBase::Ptr &grid_template,
|
||||
const AttributeIDRef &attribute_id)
|
||||
{
|
||||
openvdb::GridBase::Ptr result = nullptr;
|
||||
volume_grid_to_static_type_tag(grid_type, [&](auto tag) {
|
||||
using GridType = typename decltype(tag)::type;
|
||||
if (grid_template) {
|
||||
typename GridType::Ptr typed_grid = GridType::create(*grid_template);
|
||||
result = typed_grid;
|
||||
volume_grid_to_static_type_tag(BKE_volume_grid_type_openvdb(*grid_template), [&](auto tag) {
|
||||
using GridType = typename decltype(tag)::type;
|
||||
typename GridType::Ptr typed_template = openvdb::GridBase::grid<GridType>(grid_template);
|
||||
BLI_assert(typed_template != nullptr);
|
||||
typed_grid->topologyUnion(*typed_template);
|
||||
});
|
||||
}
|
||||
else {
|
||||
result = GridType::create();
|
||||
}
|
||||
});
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (attribute_id.is_anonymous()) {
|
||||
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
|
||||
result->setName(anonymous_id.name());
|
||||
}
|
||||
else {
|
||||
result->setName(attribute_id.name());
|
||||
}
|
||||
grids.emplace_back(VolumeGrid{result});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static openvdb::GridBase::Ptr add_generic_grid_with_varray(
|
||||
VolumeGridVector &grids,
|
||||
const VolumeGridType grid_type,
|
||||
const eCDAllocType /*alloctype*/,
|
||||
const openvdb::GridBase::Ptr &grid_template,
|
||||
const AttributeIDRef &attribute_id,
|
||||
const GVArray &varray)
|
||||
{
|
||||
openvdb::GridBase::Ptr result = add_generic_grid(
|
||||
grids, grid_type, CD_CONSTRUCT, grid_template, attribute_id);
|
||||
if (result != nullptr) {
|
||||
GVMutableArray dst_varray = get_volume_vmutablearray<VArrayImpl_For_VolumeGridValue>(
|
||||
*result, grid_type);
|
||||
volume_grid_to_static_type_tag(grid_type, [&](auto tag) {
|
||||
using GridType = typename decltype(tag)::type;
|
||||
using VArrayImplType = VArrayImpl_For_VolumeGridValue<GridType>;
|
||||
using AttributeType = typename VArrayImplType::AttributeType;
|
||||
|
||||
VArray<AttributeType> typed_varray = varray.typed<AttributeType>();
|
||||
dst_varray.try_assign_VArray(typed_varray);
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static openvdb::GridBase::Ptr add_generic_grid_with_data(
|
||||
VolumeGridVector &grids,
|
||||
const VolumeGridType grid_type,
|
||||
const eCDAllocType /*alloctype*/,
|
||||
const openvdb::GridBase::Ptr &grid_template,
|
||||
const AttributeIDRef &attribute_id,
|
||||
const void *data,
|
||||
const ImplicitSharingInfo * /*sharing_info*/)
|
||||
{
|
||||
openvdb::GridBase::Ptr result = add_generic_grid(
|
||||
grids, grid_type, CD_CONSTRUCT, grid_template, attribute_id);
|
||||
if (result != nullptr) {
|
||||
GVMutableArray dst_varray = get_volume_vmutablearray<VArrayImpl_For_VolumeGridValue>(
|
||||
*result, grid_type);
|
||||
dst_varray.set_all(data);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool add_grid_from_attribute_init(const AttributeIDRef &attribute_id,
|
||||
VolumeGridVector &grids,
|
||||
const VolumeGridType grid_type,
|
||||
const openvdb::GridBase::Ptr &grid_template,
|
||||
const AttributeInit &initializer)
|
||||
{
|
||||
switch (initializer.type) {
|
||||
case AttributeInit::Type::Construct: {
|
||||
const openvdb::GridBase::Ptr result = add_generic_grid(
|
||||
grids, grid_type, CD_CONSTRUCT, grid_template, attribute_id);
|
||||
return result != nullptr;
|
||||
}
|
||||
case AttributeInit::Type::DefaultValue: {
|
||||
const openvdb::GridBase::Ptr result = add_generic_grid(
|
||||
grids, grid_type, CD_SET_DEFAULT, grid_template, attribute_id);
|
||||
return result != nullptr;
|
||||
}
|
||||
case AttributeInit::Type::VArray: {
|
||||
const GVArray &varray =
|
||||
static_cast<const blender::bke::AttributeInitVArray &>(initializer).varray;
|
||||
const openvdb::GridBase::Ptr result = add_generic_grid_with_varray(
|
||||
grids, grid_type, CD_SET_DEFAULT, grid_template, attribute_id, varray);
|
||||
return result != nullptr;
|
||||
}
|
||||
case AttributeInit::Type::MoveArray: {
|
||||
void *data = static_cast<const blender::bke::AttributeInitMoveArray &>(initializer).data;
|
||||
const openvdb::GridBase::ConstPtr result = add_generic_grid_with_data(
|
||||
grids, grid_type, CD_CONSTRUCT, grid_template, attribute_id, data, nullptr);
|
||||
return result != nullptr;
|
||||
}
|
||||
case AttributeInit::Type::Shared: {
|
||||
const AttributeInitShared &init = static_cast<const blender::bke::AttributeInitShared &>(
|
||||
initializer);
|
||||
const openvdb::GridBase::ConstPtr result = add_generic_grid_with_data(grids,
|
||||
grid_type,
|
||||
CD_CONSTRUCT,
|
||||
grid_template,
|
||||
attribute_id,
|
||||
init.data,
|
||||
init.sharing_info);
|
||||
return result != nullptr;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VolumeCustomAttributeProvider::try_create(void *owner,
|
||||
const AttributeIDRef &attribute_id,
|
||||
const eAttrDomain domain,
|
||||
const eCustomDataType data_type,
|
||||
const AttributeInit &initializer) const
|
||||
{
|
||||
if (!attribute_id) {
|
||||
return false;
|
||||
}
|
||||
if (domain_ != domain) {
|
||||
return false;
|
||||
}
|
||||
if (!this->type_is_supported(data_type)) {
|
||||
return false;
|
||||
}
|
||||
VolumeGridVector &grids = grid_access_.get_grids(owner);
|
||||
if (grids.find_grid(attribute_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const openvdb::GridBase::Ptr grid_template = grids.empty() ? nullptr : grids.front().grid();
|
||||
const VolumeGridType grid_type = grid_type_for_custom_data_type(data_type);
|
||||
if (!add_grid_from_attribute_init(attribute_id, grids, grid_type, grid_template, initializer)) {
|
||||
return false;
|
||||
}
|
||||
if (update_on_change_ != nullptr) {
|
||||
update_on_change_(owner);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VolumeCustomAttributeProvider::foreach_attribute(
|
||||
const void *owner, const AttributeForeachCallback callback) const
|
||||
{
|
||||
const VolumeGridVector &grids = grid_access_.get_const_grids(owner);
|
||||
|
||||
for (const VolumeGrid &grid : grids) {
|
||||
const AttributeIDRef attribute_id{grid.name()};
|
||||
const eCustomDataType data_type = custom_data_type_for_grid_type(grid.grid_type());
|
||||
if (data_type == CD_NUMTYPES) {
|
||||
continue;
|
||||
}
|
||||
const AttributeMetaData meta_data{ATTR_DOMAIN_VOXEL, data_type};
|
||||
callback(attribute_id, meta_data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
# endif // WITH_OPENVDB
|
||||
|
||||
#endif
|
||||
|
|
|
@ -16,8 +16,6 @@ namespace blender::bke {
|
|||
* components in a generic way.
|
||||
*/
|
||||
struct VolumeGridAccessInfo {
|
||||
// using GridGetter = VolumeGeometryGrid &(*)(void *owner);
|
||||
// using ConstGridGetter = const VolumeGeometryGrid &(*)(const void *owner);
|
||||
using GridGetter = VolumeGridVector &(*)(void *owner);
|
||||
using ConstGridGetter = const VolumeGridVector &(*)(const void *owner);
|
||||
|
||||
|
@ -114,83 +112,4 @@ class VolumeCustomAttributeGridProvider final : public DynamicAttributesProvider
|
|||
// bool exists(const void *owner) const final;
|
||||
// };
|
||||
|
||||
#if 0
|
||||
class VolumeGridPositionAttributeProvider final : public BuiltinAttributeProvider {
|
||||
using UpdateOnChange = void (*)(void *owner);
|
||||
const VolumeGridAccessInfo grid_access_;
|
||||
const UpdateOnChange update_on_change_;
|
||||
|
||||
public:
|
||||
VolumeGridPositionAttributeProvider(std::string attribute_name,
|
||||
const eAttrDomain domain,
|
||||
const VolumeGridAccessInfo grid_access,
|
||||
const UpdateOnChange update_on_write,
|
||||
const AttributeValidator validator = {})
|
||||
: BuiltinAttributeProvider(std::move(attribute_name),
|
||||
domain,
|
||||
CD_AUTO_FROM_NAME,
|
||||
NonCreatable,
|
||||
NonDeletable,
|
||||
validator),
|
||||
grid_access_(grid_access),
|
||||
update_on_change_(update_on_write)
|
||||
{
|
||||
}
|
||||
|
||||
GAttributeReader try_get_for_read(const void *owner) const final;
|
||||
GAttributeWriter try_get_for_write(void *owner) const final;
|
||||
bool try_delete(void *owner) const final;
|
||||
bool try_create(void *owner, const AttributeInit &initializer) const final;
|
||||
bool exists(const void *owner) const final;
|
||||
};
|
||||
|
||||
/**
|
||||
* An attribute provider for custom volume grids.
|
||||
*/
|
||||
class VolumeCustomAttributeProvider final : public DynamicAttributesProvider {
|
||||
private:
|
||||
using UpdateOnChange = void (*)(void *owner);
|
||||
static constexpr uint64_t supported_types_mask = CD_MASK_PROP_FLOAT | CD_MASK_PROP_FLOAT3 |
|
||||
CD_MASK_PROP_INT32 | CD_MASK_PROP_BOOL;
|
||||
const eAttrDomain domain_;
|
||||
const VolumeGridAccessInfo grid_access_;
|
||||
const UpdateOnChange update_on_change_;
|
||||
|
||||
public:
|
||||
VolumeCustomAttributeProvider(const eAttrDomain domain,
|
||||
const VolumeGridAccessInfo grid_access,
|
||||
UpdateOnChange update_on_change)
|
||||
: domain_(domain), grid_access_(grid_access), update_on_change_(update_on_change)
|
||||
{
|
||||
}
|
||||
|
||||
GAttributeReader try_get_for_read(const void *owner,
|
||||
const AttributeIDRef &attribute_id) const final;
|
||||
|
||||
GAttributeWriter try_get_for_write(void *owner, const AttributeIDRef &attribute_id) const final;
|
||||
|
||||
bool try_delete(void *owner, const AttributeIDRef &attribute_id) const final;
|
||||
|
||||
bool try_create(void *owner,
|
||||
const AttributeIDRef &attribute_id,
|
||||
eAttrDomain domain,
|
||||
const eCustomDataType data_type,
|
||||
const AttributeInit &initializer) const final;
|
||||
|
||||
bool foreach_attribute(const void *owner, const AttributeForeachCallback callback) const final;
|
||||
|
||||
void foreach_domain(const FunctionRef<void(eAttrDomain)> callback) const final
|
||||
{
|
||||
callback(domain_);
|
||||
}
|
||||
|
||||
private:
|
||||
bool type_is_supported(eCustomDataType data_type) const
|
||||
{
|
||||
return ((1ULL << data_type) & supported_types_mask) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_volume.h"
|
||||
#include "BKE_volume_geometry.hh"
|
||||
|
||||
#include "attribute_access_volume.hh"
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_volume.h"
|
||||
#include "BKE_volume_geometry.hh"
|
||||
#include "BKE_volume_openvdb.hh"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
@ -121,8 +120,6 @@ static void volume_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, con
|
|||
#endif
|
||||
|
||||
volume_dst->batch_cache = nullptr;
|
||||
|
||||
// new (&volume_dst->geometry) blender::bke::VolumeGeometry(volume_src->geometry.wrap());
|
||||
}
|
||||
|
||||
static void volume_free_data(ID *id)
|
||||
|
@ -135,8 +132,6 @@ static void volume_free_data(ID *id)
|
|||
MEM_delete(volume->runtime.grids);
|
||||
volume->runtime.grids = nullptr;
|
||||
#endif
|
||||
|
||||
// volume->geometry.wrap().~VolumeGeometry();
|
||||
}
|
||||
|
||||
static void volume_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
|
@ -165,8 +160,7 @@ static void volume_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
|||
Volume *volume = reinterpret_cast<Volume *>(id);
|
||||
|
||||
if (volume->packedfile != nullptr &&
|
||||
(bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0)
|
||||
{
|
||||
(bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -194,8 +188,6 @@ static void volume_blend_write(BlendWriter *writer, ID *id, const void *id_addre
|
|||
BLO_write_pointer_array(writer, volume->totcol, volume->mat);
|
||||
|
||||
BKE_packedfile_blend_write(writer, volume->packedfile);
|
||||
|
||||
// volume->geometry.wrap().blend_write(*writer, *id);
|
||||
}
|
||||
|
||||
static void volume_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
|
@ -207,8 +199,6 @@ static void volume_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
|
||||
/* materials */
|
||||
BLO_read_pointer_array(reader, (void **)&volume->mat);
|
||||
|
||||
// volume->geometry.wrap().blend_read_data(*reader);
|
||||
}
|
||||
|
||||
static void volume_blend_read_lib(BlendLibReader *reader, ID *id)
|
||||
|
|
|
@ -1,191 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
||||
# include "DNA_volume_types.h"
|
||||
|
||||
# include "BKE_volume_geometry.hh"
|
||||
|
||||
# include "attribute_access_volume.hh"
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name VolumeGeometry
|
||||
* \{ */
|
||||
|
||||
VolumeGeometry::VolumeGeometry() {}
|
||||
|
||||
/**
|
||||
* \note Expects `dst` to be initialized, since the original attributes must be freed.
|
||||
*/
|
||||
static void copy_volume_geometry(VolumeGeometry &dst, const VolumeGeometry &src)
|
||||
{
|
||||
dst.grid = static_cast<VolumeGeometryGrid *>(MEM_dupallocN(src.grid));
|
||||
}
|
||||
|
||||
VolumeGeometry::VolumeGeometry(const VolumeGeometry &other) : VolumeGeometry()
|
||||
{
|
||||
copy_volume_geometry(*this, other);
|
||||
}
|
||||
|
||||
VolumeGeometry &VolumeGeometry::operator=(const VolumeGeometry &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
copy_volume_geometry(*this, other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* The source should be empty, but in a valid state so that using it further will work. */
|
||||
static void move_volume_geometry(VolumeGeometry &dst, VolumeGeometry &src)
|
||||
{
|
||||
std::swap(dst.grid, src.grid);
|
||||
src.grid = nullptr;
|
||||
}
|
||||
|
||||
VolumeGeometry::VolumeGeometry(VolumeGeometry &&other) : VolumeGeometry()
|
||||
{
|
||||
move_volume_geometry(*this, other);
|
||||
}
|
||||
|
||||
VolumeGeometry &VolumeGeometry::operator=(VolumeGeometry &&other)
|
||||
{
|
||||
if (this != &other) {
|
||||
move_volume_geometry(*this, other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
VolumeGeometry::~VolumeGeometry()
|
||||
{
|
||||
if (grid) {
|
||||
MEM_delete(grid);
|
||||
}
|
||||
}
|
||||
|
||||
int VolumeGeometry::domain_size(eAttrDomain domain) const
|
||||
{
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_VOXEL:
|
||||
return grid ? int(grid->active_voxel_num()) : 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef WITH_OPENVDB
|
||||
void VolumeGeometry::set_grid(const openvdb::GridBase::Ptr &grid_ptr)
|
||||
{
|
||||
if (grid == nullptr) {
|
||||
grid = MEM_new<VolumeGeometryGrid>(__func__);
|
||||
}
|
||||
grid->grid_ = grid_ptr;
|
||||
}
|
||||
# endif
|
||||
|
||||
/**
|
||||
* In this function all the attribute providers for a volume component are created.
|
||||
* Most data in this function is statically allocated, because it does not change over time.
|
||||
*/
|
||||
static ComponentAttributeProviders create_attribute_providers_for_volume()
|
||||
{
|
||||
static VolumeGridAccessInfo grid_access = {
|
||||
[](void *owner) -> VolumeGeometryGrid & {
|
||||
return *static_cast<VolumeGeometryGrid *>(owner);
|
||||
},
|
||||
[](const void *owner) -> const VolumeGeometryGrid & {
|
||||
return *static_cast<const VolumeGeometryGrid *>(owner);
|
||||
},
|
||||
};
|
||||
|
||||
static auto update_on_change = [](void * /*owner*/) {};
|
||||
|
||||
// static BuiltinVolumeAttributeProvider position("position",
|
||||
// ATTR_DOMAIN_VOXEL,
|
||||
// CD_PROP_FLOAT3,
|
||||
// BuiltinAttributeProvider::NonCreatable,
|
||||
// BuiltinAttributeProvider::NonDeletable,
|
||||
// grid_access,
|
||||
// update_on_change);
|
||||
|
||||
static VolumeGridValueAttributeProvider value(
|
||||
"value", ATTR_DOMAIN_VOXEL, grid_access, update_on_change);
|
||||
|
||||
// static VolumeAttributeProvider voxel_custom_data(ATTR_DOMAIN_VOXEL, grid_access);
|
||||
|
||||
// return ComponentAttributeProviders({&position}, {&voxel_custom_data});
|
||||
return ComponentAttributeProviders({&value}, {});
|
||||
}
|
||||
|
||||
static AttributeAccessorFunctions get_volume_accessor_functions()
|
||||
{
|
||||
static const ComponentAttributeProviders providers = create_attribute_providers_for_volume();
|
||||
AttributeAccessorFunctions fn =
|
||||
attribute_accessor_functions::accessor_functions_for_providers<providers>();
|
||||
/* Set domain callbacks that are not defined yet. */
|
||||
fn.domain_size = [](const void *owner, const eAttrDomain domain) {
|
||||
if (owner == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
const VolumeGeometry &geometry = *static_cast<const VolumeGeometry *>(owner);
|
||||
return geometry.domain_size(domain);
|
||||
};
|
||||
fn.domain_supported = [](const void * /*owner*/, const eAttrDomain domain) {
|
||||
return ELEM(domain, ATTR_DOMAIN_VOXEL);
|
||||
};
|
||||
fn.adapt_domain = [](const void *owner,
|
||||
const GVArray &varray,
|
||||
const eAttrDomain from_domain,
|
||||
const eAttrDomain to_domain) -> GVArray {
|
||||
if (owner == nullptr) {
|
||||
return {};
|
||||
}
|
||||
const VolumeGeometry &geometry = *static_cast<const VolumeGeometry *>(owner);
|
||||
return geometry.adapt_domain(varray, from_domain, to_domain);
|
||||
};
|
||||
return fn;
|
||||
}
|
||||
|
||||
static const AttributeAccessorFunctions &get_volume_accessor_functions_ref()
|
||||
{
|
||||
static const AttributeAccessorFunctions fn = get_volume_accessor_functions();
|
||||
return fn;
|
||||
}
|
||||
|
||||
AttributeAccessor VolumeGeometry::attributes() const
|
||||
{
|
||||
return AttributeAccessor(grid, get_volume_accessor_functions_ref());
|
||||
}
|
||||
|
||||
MutableAttributeAccessor VolumeGeometry::attributes_for_write()
|
||||
{
|
||||
return MutableAttributeAccessor(grid, get_volume_accessor_functions_ref());
|
||||
}
|
||||
|
||||
GVArray VolumeGeometry::adapt_domain(const GVArray &varray, eAttrDomain from, eAttrDomain to) const
|
||||
{
|
||||
if (from == to) {
|
||||
return varray;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void VolumeGeometry::blend_read_data(BlendDataReader & /*reader*/)
|
||||
{
|
||||
grid = nullptr;
|
||||
}
|
||||
|
||||
void VolumeGeometry::blend_write(BlendWriter & /*writer*/, ID & /*id*/) {}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::bke
|
||||
|
||||
#endif
|
|
@ -361,16 +361,6 @@ static ComponentAttributeProviders create_attribute_providers_for_volume()
|
|||
static VolumeCustomAttributeGridProvider grid_custom_data(
|
||||
ATTR_DOMAIN_VOXEL, grid_access, update_on_change);
|
||||
|
||||
// static VolumeGridPositionAttributeProvider position(
|
||||
// "position", ATTR_DOMAIN_VOXEL, grid_access, update_on_change);
|
||||
|
||||
// static VolumeGridValueAttributeProvider value(
|
||||
// "value", ATTR_DOMAIN_VOXEL, grid_access, update_on_change);
|
||||
|
||||
// static VolumeCustomAttributeProvider voxel_custom_data(
|
||||
// ATTR_DOMAIN_VOXEL, grid_access, update_on_change);
|
||||
|
||||
// return ComponentAttributeProviders({&position}, {&voxel_custom_data});
|
||||
return ComponentAttributeProviders({}, {&grid_custom_data});
|
||||
}
|
||||
|
||||
|
|
|
@ -46,8 +46,6 @@ template<typename T, Index N1 = 5, Index N2 = 4, Index N3 = 3> struct Tree4Fwd {
|
|||
};
|
||||
} // namespace tree
|
||||
namespace points {
|
||||
// template<typename IntType_, Index Kind> struct PointIndex;
|
||||
// using PointDataIndex32 = PointIndex<Index32, 1>;
|
||||
template<typename T, Index Log2Dim> class PointDataLeafNode;
|
||||
using PointDataTree = tree::Tree<tree::RootNode<
|
||||
tree::InternalNode<tree::InternalNode<PointDataLeafNode<PointDataIndex32, 3>, 4>, 5>>>;
|
||||
|
@ -98,24 +96,7 @@ using VectorGrid = Vec3fGrid;
|
|||
} // namespace openvdb
|
||||
#endif
|
||||
|
||||
namespace blender {
|
||||
|
||||
///* XXX OpenVDB expects some math functions on vector types. */
|
||||
// template<typename T, int Size> inline VecBase<T, Size> Abs(VecBase<T, Size> v)
|
||||
//{
|
||||
// VecBase<T, Size> r;
|
||||
// for (int i = 0; i < Size; i++) {
|
||||
// r[i] = math::abs(v[i]);
|
||||
// }
|
||||
// return r;
|
||||
// }
|
||||
///* Specialization: math::abs is not defined for unsigned types. */
|
||||
// template<int Size> inline VecBase<uint32_t, Size> Abs(VecBase<uint32_t, Size> v)
|
||||
//{
|
||||
// return v;
|
||||
// }
|
||||
|
||||
namespace volume {
|
||||
namespace blender::volume {
|
||||
|
||||
#ifdef WITH_OPENVDB
|
||||
namespace grid_types {
|
||||
|
@ -263,48 +244,8 @@ template<> struct Converter<openvdb::BoolGrid> {
|
|||
};
|
||||
|
||||
/* TODO add more as needed. */
|
||||
/* TODO could use template magic to generate all from 1 list, but not worth it for now. */
|
||||
/* TODO some types disabled because of missing CPPType registration. */
|
||||
|
||||
// using BoolTree = TreeCommon<bool>;
|
||||
// using MaskTree = TreeCommon<openvdb::ValueMask>;
|
||||
// using FloatTree = TreeCommon<float>;
|
||||
// using Float2Tree = TreeCommon<float2>;
|
||||
// using Float3Tree = TreeCommon<float3>;
|
||||
//// using Float4Tree = TreeCommon<float4>;
|
||||
// using DoubleTree = TreeCommon<double>;
|
||||
// using Double3Tree = TreeCommon<double3>;
|
||||
// using IntTree = TreeCommon<int32_t>;
|
||||
// using Int2Tree = TreeCommon<int2>;
|
||||
// using Int3Tree = TreeCommon<int3>;
|
||||
//// using Int4Tree = TreeCommon<int4>;
|
||||
// using UIntTree = TreeCommon<uint32_t>;
|
||||
//// using UInt2Tree = TreeCommon<uint2>;
|
||||
//// using UInt3Tree = TreeCommon<uint3>;
|
||||
//// using UInt4Tree = TreeCommon<uint4>;
|
||||
// using ScalarTree = FloatTree;
|
||||
// using TopologyTree = MaskTree;
|
||||
//
|
||||
// using BoolGrid = openvdb::Grid<BoolTree>;
|
||||
// using MaskGrid = openvdb::Grid<MaskTree>;
|
||||
// using FloatGrid = openvdb::Grid<FloatTree>;
|
||||
// using Float2Grid = openvdb::Grid<Float2Tree>;
|
||||
// using Float3Grid = openvdb::Grid<Float3Tree>;
|
||||
//// using Float4Grid = openvdb::Grid<Float4Tree>;
|
||||
// using DoubleGrid = openvdb::Grid<DoubleTree>;
|
||||
// using Double3Grid = openvdb::Grid<Double3Tree>;
|
||||
// using IntGrid = openvdb::Grid<IntTree>;
|
||||
// using Int2Grid = openvdb::Grid<Int2Tree>;
|
||||
// using Int3Grid = openvdb::Grid<Int3Tree>;
|
||||
//// using Int4Grid = openvdb::Grid<Int4Tree>;
|
||||
// using UIntGrid = openvdb::Grid<UIntTree>;
|
||||
//// using UInt2Grid = openvdb::Grid<UInt2Tree>;
|
||||
//// using UInt3Grid = openvdb::Grid<UInt3Tree>;
|
||||
//// using UInt4Grid = openvdb::Grid<UInt4Tree>;
|
||||
// using ScalarGrid = openvdb::Grid<ScalarTree>;
|
||||
// using TopologyGrid = openvdb::Grid<TopologyTree>;
|
||||
// using PointDataGrid = openvdb::points::PointDataGrid;
|
||||
|
||||
using SupportedAttributeValueTypes = std::tuple<bool,
|
||||
float,
|
||||
float2,
|
||||
|
@ -540,6 +481,4 @@ template<typename T> MutableGrid<T>::operator GMutableGrid const() const
|
|||
|
||||
/** \} */
|
||||
|
||||
} // namespace volume
|
||||
|
||||
} // namespace blender
|
||||
} // namespace blender::volume
|
||||
|
|
|
@ -27,13 +27,6 @@ namespace blender::volume {
|
|||
|
||||
#ifdef WITH_OPENVDB
|
||||
|
||||
namespace grid_types {
|
||||
|
||||
// extern template struct AttributeValueConverter<float>;
|
||||
// extern template struct GridValueConverter<openvdb::FloatGrid>;
|
||||
|
||||
} // namespace grid_types
|
||||
|
||||
template<typename T> Grid<T> GGrid::typed() const
|
||||
{
|
||||
# ifdef WITH_OPENVDB
|
||||
|
|
|
@ -272,11 +272,6 @@ template<typename GridType, typename MaskGridType> struct EvalPerLeafOp {
|
|||
}
|
||||
|
||||
/* Pass output buffer to the procedure executor. */
|
||||
// ValueType *leaf_values = leaf.buffer().data();
|
||||
// MutableSpan<ValueType> leaf_span = {leaf_values, leaf_size};
|
||||
// const GMutableSpan out_span =
|
||||
// volume::grid_types::Converter<GridType>::leaf_buffer_to_varray(
|
||||
// leaf_span);
|
||||
auto *leaf_values = leaf.buffer().data();
|
||||
MutableSpan<std::decay_t<decltype(*leaf_values)>> leaf_span = {leaf_values, leaf_size};
|
||||
const GMutableSpan out_span = volume::grid_types::Converter<GridType>::leaf_buffer_to_varray(
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "BLI_math_matrix.hh"
|
||||
|
||||
#include "BKE_volume.h"
|
||||
#include "BKE_volume_geometry.hh"
|
||||
#include "BKE_volume_openvdb.hh"
|
||||
|
||||
#include "DNA_volume_types.h"
|
||||
|
|
|
@ -58,15 +58,6 @@ typedef struct VolumeRender {
|
|||
float clipping;
|
||||
} VolumeRender;
|
||||
|
||||
// typedef struct VolumeGeometry {
|
||||
// struct VolumeGeometryGrid *grid;
|
||||
//
|
||||
// #ifdef __cplusplus
|
||||
// blender::bke::VolumeGeometry &wrap();
|
||||
// const blender::bke::VolumeGeometry &wrap() const;
|
||||
// #endif
|
||||
// } VolumeGeometry;
|
||||
|
||||
typedef struct Volume {
|
||||
ID id;
|
||||
struct AnimData *adt; /* animation data (must be immediately after id) */
|
||||
|
@ -110,9 +101,6 @@ typedef struct Volume {
|
|||
/* Factor for velocity vector for artistic control. */
|
||||
float velocity_scale;
|
||||
|
||||
/* Grid geometry */
|
||||
// VolumeGeometry geometry;
|
||||
|
||||
/* Draw Cache */
|
||||
void *batch_cache;
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#include "BKE_type_conversions.hh"
|
||||
#include "BKE_volume_attribute.hh"
|
||||
#include "BKE_volume_geometry.hh"
|
||||
#include "BKE_volume_openvdb.hh"
|
||||
|
||||
#include "BLI_virtual_array.hh"
|
||||
|
|
Loading…
Reference in New Issue