Before, it was only possible to apply modifiers through a multires modifier if they were deform-only. The Geometry Nodes modifier is of course not deform-only. However, often one can build a node setup, that only deforms and does nothing else. To make it possible to apply the Geometry Nodes modifier in such cases the following things had to be done: * Update `BKE_modifier_deform_verts` to work with modifiers that implement `modify_geometry_set` instead of `deform_verts`. * Add error handling for the case when `modify_geometry_set` does more than just deformation. * Allow the Geometry Nodes modifier to be applied through a multi-res modifier. Two new utility types (`ArrayState` and `MeshTopologyState`) have been introduced to allow for efficient and accurate checking whether the topology has been modified. In common cases, they can detect that the topology has not been changed in constant time, but they fall back to linear time checking if it's not immediately obvious that the topology has not been changed. This works with the example files from #98559 and #97603. Pull Request: https://projects.blender.org/blender/blender/pulls/131904
62 lines
1.9 KiB
C++
62 lines
1.9 KiB
C++
/* SPDX-FileCopyrightText: 2024 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 */
|
|
|
|
#include "testing/testing.h"
|
|
|
|
#include "BLI_array_state.hh"
|
|
|
|
namespace blender::tests {
|
|
|
|
TEST(array_state, Empty)
|
|
{
|
|
ArrayState<int> state{};
|
|
EXPECT_TRUE(state.is_empty());
|
|
EXPECT_TRUE(state.same_as({}, nullptr));
|
|
EXPECT_FALSE(state.same_as(VArray<int>::ForSpan({3, 4}), nullptr));
|
|
}
|
|
|
|
TEST(array_state, NoSharing)
|
|
{
|
|
ArrayState<int> state{VArray<int>::ForSpan({1, 2, 3}), nullptr};
|
|
EXPECT_FALSE(state.is_empty());
|
|
EXPECT_TRUE(state.same_as(VArray<int>::ForSpan({1, 2, 3}), nullptr));
|
|
EXPECT_FALSE(state.same_as(VArray<int>::ForSpan({1, 2, 4}), nullptr));
|
|
EXPECT_FALSE(state.same_as(VArray<int>::ForSpan({1, 2, 3, 4}), nullptr));
|
|
}
|
|
|
|
TEST(array_state, WithSharing)
|
|
{
|
|
int *data = MEM_cnew_array<int>(3, __func__);
|
|
data[0] = 0;
|
|
data[1] = 10;
|
|
data[2] = 20;
|
|
ImplicitSharingPtr sharing_info{implicit_sharing::info_for_mem_free(data)};
|
|
|
|
ArrayState<int> state{VArray<int>::ForSpan({data, 3}), sharing_info.get()};
|
|
EXPECT_FALSE(state.is_empty());
|
|
EXPECT_TRUE(state.same_as(VArray<int>::ForSpan({data, 3}), sharing_info.get()));
|
|
EXPECT_TRUE(state.same_as(VArray<int>::ForSpan({0, 10, 20}), nullptr));
|
|
EXPECT_FALSE(state.same_as(VArray<int>::ForSpan({0, 1, 2}), nullptr));
|
|
}
|
|
|
|
TEST(array_state, DifferentSharingInfoButSameData)
|
|
{
|
|
int *data1 = MEM_cnew_array<int>(3, __func__);
|
|
data1[0] = 0;
|
|
data1[1] = 10;
|
|
data1[2] = 20;
|
|
ImplicitSharingPtr sharing_info1{implicit_sharing::info_for_mem_free(data1)};
|
|
|
|
int *data2 = MEM_cnew_array<int>(3, __func__);
|
|
data2[0] = 0;
|
|
data2[1] = 10;
|
|
data2[2] = 20;
|
|
ImplicitSharingPtr sharing_info2{implicit_sharing::info_for_mem_free(data2)};
|
|
|
|
ArrayState<int> state{VArray<int>::ForSpan({data1, 3}), sharing_info1.get()};
|
|
EXPECT_TRUE(state.same_as(VArray<int>::ForSpan({data2, 3}), sharing_info2.get()));
|
|
}
|
|
|
|
} // namespace blender::tests
|