Blender V5.0
volume_grid_fields.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
7
8#include "BLT_translation.hh"
9
10#ifdef WITH_OPENVDB
11
12# include <openvdb/math/Transform.h>
13
14namespace blender::bke {
15
16VoxelFieldContext::VoxelFieldContext(const openvdb::math::Transform &transform,
17 const Span<openvdb::Coord> voxels)
18 : transform_(transform), voxels_(voxels)
19{
20}
21
22GVArray VoxelFieldContext::get_varray_for_input(const fn::FieldInput &field_input,
23 const IndexMask &mask,
24 ResourceScope &scope) const
25{
26 if (const auto *attribute_field = dynamic_cast<const bke::AttributeFieldInput *>(&field_input)) {
27 if (attribute_field->attribute_name() == "position") {
28 /* Support retrieving voxel positions. */
29 Array<float3> positions(voxels_.size());
30 threading::parallel_for(positions.index_range(), 1024, [&](const IndexRange range) {
31 for (const int64_t i : range) {
32 const openvdb::Coord &voxel = voxels_[i];
33 const openvdb::Vec3d position = transform_.indexToWorld(voxel);
34 positions[i] = float3(position.x(), position.y(), position.z());
35 }
36 });
37 return VArray<float3>::from_container(std::move(positions));
38 }
39 }
40 if (dynamic_cast<const fn::IndexFieldInput *>(&field_input)) {
41 return {};
42 }
43 return field_input.get_varray_for_context(*this, mask, scope);
44}
45
46TilesFieldContext::TilesFieldContext(const openvdb::math::Transform &transform,
48 : transform_(transform), tiles_(tiles)
49{
50}
51
52GVArray TilesFieldContext::get_varray_for_input(const fn::FieldInput &field_input,
53 const IndexMask &mask,
54 ResourceScope &scope) const
55{
56 if (const auto *attribute_field = dynamic_cast<const bke::AttributeFieldInput *>(&field_input)) {
57 if (attribute_field->attribute_name() == "position") {
58 /* Support retrieving tile positions. */
59 Array<float3> positions(tiles_.size());
60 threading::parallel_for(positions.index_range(), 1024, [&](const IndexRange range) {
61 for (const int64_t i : range) {
62 const openvdb::CoordBBox &tile = tiles_[i];
63 const openvdb::Vec3d position = transform_.indexToWorld(tile.getCenter());
64 positions[i] = float3(position.x(), position.y(), position.z());
65 }
66 });
67 return VArray<float3>::from_container(std::move(positions));
68 }
69 }
70 if (dynamic_cast<const fn::IndexFieldInput *>(&field_input)) {
71 return {};
72 }
73 return field_input.get_varray_for_context(*this, mask, scope);
74}
75
76VoxelCoordinateFieldInput::VoxelCoordinateFieldInput(const math::Axis axis)
77 : fn::FieldInput(CPPType::get<int>(), TIP_("Voxel Coordinate")), axis_(axis)
78{
79}
80
81GVArray VoxelCoordinateFieldInput::get_varray_for_context(const fn::FieldContext &context,
82 const IndexMask &mask,
83 ResourceScope & /*scope*/) const
84{
85 if (const auto *voxel_context = dynamic_cast<const VoxelFieldContext *>(&context)) {
86 const Span<openvdb::Coord> voxels = voxel_context->voxels();
87 Array<int> result(mask.min_array_size());
88 mask.foreach_index_optimized<int>([&](const int i) { result[i] = voxels[i][axis_.as_int()]; });
89 return VArray<int>::from_container(std::move(result));
90 }
91 if (const auto *tiles_context = dynamic_cast<const TilesFieldContext *>(&context)) {
92 const Span<openvdb::CoordBBox> tiles = tiles_context->tiles();
93 Array<int> result(mask.min_array_size());
94 mask.foreach_index_optimized<int>(
95 [&](const int i) { result[i] = tiles[i].min()[axis_.as_int()]; });
96 return VArray<int>::from_container(std::move(result));
97 }
98 return {};
99}
100
101VoxelExtentFieldInput::VoxelExtentFieldInput(const math::Axis axis)
102 : fn::FieldInput(CPPType::get<int>(), TIP_("Voxel Extent")), axis_(axis)
103{
104}
105
106GVArray VoxelExtentFieldInput::get_varray_for_context(const fn::FieldContext &context,
107 const IndexMask &mask,
108 ResourceScope & /*scope*/) const
109{
110 if (dynamic_cast<const VoxelFieldContext *>(&context)) {
111 return VArray<int>::from_single(1, mask.min_array_size());
112 }
113 if (const auto *tiles_context = dynamic_cast<const TilesFieldContext *>(&context)) {
114 const Span<openvdb::CoordBBox> tiles = tiles_context->tiles();
115 Array<int> result(mask.min_array_size());
116 mask.foreach_index_optimized<int>(
117 [&](const int i) { result[i] = tiles[i].dim()[axis_.as_int()]; });
118 return VArray<int>::from_container(std::move(result));
119 }
120 return {};
121}
122
123IsTileFieldInput::IsTileFieldInput() : fn::FieldInput(CPPType::get<bool>(), TIP_("Is Tile")) {}
124
125GVArray IsTileFieldInput::get_varray_for_context(const fn::FieldContext &context,
126 const IndexMask &mask,
127 ResourceScope & /*scope*/) const
128{
129 if (dynamic_cast<const VoxelFieldContext *>(&context)) {
130 return VArray<bool>::from_single(false, mask.min_array_size());
131 }
132 if (dynamic_cast<const TilesFieldContext *>(&context)) {
133 return VArray<bool>::from_single(true, mask.min_array_size());
134 }
135 return {};
136}
137
138} // namespace blender::bke
139
140#endif
#define TIP_(msgid)
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static VArray from_single(T value, const int64_t size)
static VArray from_container(ContainerT container)
ccl_gpu_kernel_postfix ccl_global KernelWorkTile * tiles
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
std::shared_ptr< const T > get(const GenericKey &key, FunctionRef< std::unique_ptr< T >()> compute_fn)
i
Definition text_draw.cc:230