| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-2.0 | ||
| 3 | |||
| 4 | /// @file compiler/PointExecutable.cc | ||
| 5 | |||
| 6 | #include "PointExecutable.h" | ||
| 7 | #include "Logger.h" | ||
| 8 | |||
| 9 | #include "openvdb_ax/ast/Scanners.h" | ||
| 10 | #include "openvdb_ax/Exceptions.h" | ||
| 11 | // @TODO refactor so we don't have to include PointComputeGenerator.h, | ||
| 12 | // but still have the functions defined in one place | ||
| 13 | #include "openvdb_ax/codegen/PointComputeGenerator.h" | ||
| 14 | #include "openvdb_ax/codegen/PointLeafLocalData.h" | ||
| 15 | #include "openvdb_ax/codegen/Codecs.h" | ||
| 16 | |||
| 17 | #include <openvdb/Types.h> | ||
| 18 | |||
| 19 | #include <openvdb/points/AttributeArray.h> | ||
| 20 | #include <openvdb/points/PointAttribute.h> | ||
| 21 | #include <openvdb/points/PointConversion.h> // ConversionTraits | ||
| 22 | #include <openvdb/points/PointDataGrid.h> | ||
| 23 | #include <openvdb/points/PointGroup.h> | ||
| 24 | #include <openvdb/points/PointMask.h> | ||
| 25 | #include <openvdb/points/PointMove.h> | ||
| 26 | #include <openvdb/points/PointDelete.h> | ||
| 27 | |||
| 28 | namespace openvdb { | ||
| 29 | OPENVDB_USE_VERSION_NAMESPACE | ||
| 30 | namespace OPENVDB_VERSION_NAME { | ||
| 31 | |||
| 32 | namespace ax { | ||
| 33 | |||
| 34 | struct PointExecutable::Settings | ||
| 35 | { | ||
| 36 | bool mCreateMissing = true; | ||
| 37 | size_t mGrainSize = 1; | ||
| 38 | std::string mGroup = ""; | ||
| 39 | //IterType mValueIterator = IterType::ON; | ||
| 40 | bool mPostDelete = false; | ||
| 41 | AttributeBindings mBindings; | ||
| 42 | }; | ||
| 43 | |||
| 44 | namespace { | ||
| 45 | |||
| 46 | /// @brief Point Kernel types | ||
| 47 | /// | ||
| 48 | using KernelValueFunctionPtr = std::add_pointer<codegen::PointKernelAttributeArray::Signature>::type; | ||
| 49 | using KernelBufferRangeFunctionPtr = std::add_pointer<codegen::PointKernelBufferRange::Signature>::type; | ||
| 50 | using PointLeafLocalData = codegen::codegen_internal::PointLeafLocalData; | ||
| 51 | |||
| 52 | #ifndef NDEBUG | ||
| 53 | inline bool supported(const ast::tokens::CoreType type) | ||
| 54 | { | ||
| 55 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
|
89 | switch (type) { |
| 56 | case ast::tokens::BOOL : return true; | ||
| 57 | case ast::tokens::CHAR : return true; | ||
| 58 | case ast::tokens::INT16 : return true; | ||
| 59 | case ast::tokens::INT32 : return true; | ||
| 60 | case ast::tokens::INT64 : return true; | ||
| 61 | case ast::tokens::FLOAT : return true; | ||
| 62 | case ast::tokens::DOUBLE : return true; | ||
| 63 | case ast::tokens::VEC2I : return true; | ||
| 64 | case ast::tokens::VEC2F : return true; | ||
| 65 | case ast::tokens::VEC2D : return true; | ||
| 66 | case ast::tokens::VEC3I : return true; | ||
| 67 | case ast::tokens::VEC3F : return true; | ||
| 68 | case ast::tokens::VEC3D : return true; | ||
| 69 | case ast::tokens::VEC4I : return true; | ||
| 70 | case ast::tokens::VEC4F : return true; | ||
| 71 | case ast::tokens::VEC4D : return true; | ||
| 72 | case ast::tokens::MAT3F : return true; | ||
| 73 | case ast::tokens::MAT3D : return true; | ||
| 74 | case ast::tokens::MAT4F : return true; | ||
| 75 | case ast::tokens::MAT4D : return true; | ||
| 76 | case ast::tokens::STRING : return true; | ||
| 77 | case ast::tokens::UNKNOWN : | ||
| 78 | default : return false; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | #endif | ||
| 82 | |||
| 83 | 5089 | struct PointAttributeInfo | |
| 84 | { | ||
| 85 | PointAttributeInfo(const std::string& name, | ||
| 86 | const ast::tokens::CoreType type, | ||
| 87 | const bool write) | ||
| 88 | 5089 | : mName(name) | |
| 89 | , mType(type) | ||
| 90 |
0/4✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
5089 | , mWrite(write) {} |
| 91 | std::string mName; | ||
| 92 | ast::tokens::CoreType mType; | ||
| 93 | bool mWrite; | ||
| 94 | }; | ||
| 95 | |||
| 96 | /// @brief Shared data for the parallel operator | ||
| 97 | struct OpData | ||
| 98 | { | ||
| 99 | KernelValueFunctionPtr mKernelAttributeArray; | ||
| 100 | KernelBufferRangeFunctionPtr mKernelBufferRange; | ||
| 101 | const CustomData* mCustomData; | ||
| 102 | const AttributeRegistry* mAttributeRegistry; | ||
| 103 | size_t mIterMode; // 0 = OFF, 1 = ON, 2 = ALL | ||
| 104 | const math::Transform* mTransform; | ||
| 105 | points::AttributeSet::Descriptor::GroupIndex mGroupIndex; | ||
| 106 | std::string mPositionAttribute; | ||
| 107 | std::pair<bool,bool> mPositionAccess; | ||
| 108 | bool mUseBufferKernel; | ||
| 109 | std::vector<PointAttributeInfo> mAttributeInfo; | ||
| 110 | }; | ||
| 111 | |||
| 112 | /// @brief The arguments of the generated function | ||
| 113 | /// | ||
| 114 | struct PointFunctionArguments | ||
| 115 | { | ||
| 116 | using LeafT = points::PointDataTree::LeafNodeType; | ||
| 117 | |||
| 118 | /// @brief Base untyped handle struct for container storage | ||
| 119 | struct Handles | ||
| 120 | { | ||
| 121 | using UniquePtr = std::unique_ptr<Handles>; | ||
| 122 | virtual ~Handles() = default; | ||
| 123 | }; | ||
| 124 | |||
| 125 | /// @brief A wrapper around a VDB Points Attribute Handle, allowing for | ||
| 126 | /// typed storage of a read or write handle. This is used for | ||
| 127 | /// automatic memory management and void pointer passing into the | ||
| 128 | /// generated point functions | ||
| 129 | template <typename ValueT> | ||
| 130 | struct ReadHandle final : public Handles | ||
| 131 | { | ||
| 132 | using UniquePtr = std::unique_ptr<ReadHandle<ValueT>>; | ||
| 133 | using HandleTraits = points::point_conversion_internal::ConversionTraits<ValueT>; | ||
| 134 | using HandleT = typename HandleTraits::Handle; | ||
| 135 | 12 | ReadHandle(const LeafT& leaf, const Index idx) | |
| 136 | ✗ | : mHandle(HandleTraits::handleFromLeaf(leaf, idx)) {} | |
| 137 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
24 | ~ReadHandle() override final = default; |
| 138 | const std::unique_ptr<HandleT> mHandle; | ||
| 139 | }; | ||
| 140 | |||
| 141 | template <typename ValueT> | ||
| 142 | struct WriteHandle final : public Handles | ||
| 143 | { | ||
| 144 | using UniquePtr = std::unique_ptr<WriteHandle<ValueT>>; | ||
| 145 | using HandleTraits = points::point_conversion_internal::ConversionTraits<ValueT>; | ||
| 146 | using HandleT = typename HandleTraits::WriteHandle; | ||
| 147 | 372 | WriteHandle(LeafT& leaf, const Index idx) | |
| 148 |
19/40✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 4 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 8 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 20 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 16 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 4 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 4 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 4 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 8 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 32 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 4 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 44 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 4 times.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✓ Branch 58 taken 12 times.
✗ Branch 59 not taken.
|
408 | : mHandle(HandleTraits::writeHandleFromLeaf(leaf, idx)) {} |
| 149 |
1/2✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
|
1152 | ~WriteHandle() override final = default; |
| 150 | const std::unique_ptr<HandleT> mHandle; | ||
| 151 | }; | ||
| 152 | |||
| 153 | /////////////////////////////////////////////////////////////////////// | ||
| 154 | /////////////////////////////////////////////////////////////////////// | ||
| 155 | |||
| 156 | 1486 | PointFunctionArguments(const OpData& data, | |
| 157 | LeafT& leaf, | ||
| 158 | PointLeafLocalData* const leafLocalData) | ||
| 159 | 1486 | : mData(data) | |
| 160 | , mAttributeSet(&leaf.attributeSet()) | ||
| 161 | , mHandlesOrBuffers() | ||
| 162 | , mAttributeHandles() | ||
| 163 | , mVoidGroupHandles() | ||
| 164 | , mGroupHandles() | ||
| 165 | 1486 | , mLeafLocalData(leafLocalData) | |
| 166 | { | ||
| 167 | // add attributes based on the order and existence in the attribute registry | ||
| 168 |
2/2✓ Branch 0 taken 10150 times.
✓ Branch 1 taken 1486 times.
|
11636 | for (const auto& iter : mData.mAttributeInfo) { |
| 169 |
1/2✓ Branch 1 taken 10150 times.
✗ Branch 2 not taken.
|
10150 | this->addAttributeHandle(leaf, iter.mName, iter.mType, iter.mWrite); |
| 170 | } | ||
| 171 | |||
| 172 | // add groups | ||
| 173 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 1461 times.
|
1486 | const auto& map = mAttributeSet->descriptor().groupMap(); |
| 174 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 1461 times.
|
1486 | if (!map.empty()) { |
| 175 | // add all groups based on their offset within the attribute set - the offset can | ||
| 176 | // then be used as a key when retrieving groups from the linearized array, which | ||
| 177 | // is provided by the attribute set argument | ||
| 178 | std::map<size_t, std::string> orderedGroups; | ||
| 179 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 25 times.
|
63 | for (const auto& iter : map) { |
| 180 |
1/2✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
|
38 | orderedGroups[iter.second] = iter.first; |
| 181 | } | ||
| 182 | |||
| 183 | // add a handle at every offset up to and including the max offset. If the | ||
| 184 | // offset is not in use, we just use a null pointer as this will never be | ||
| 185 | // accessed | ||
| 186 | 25 | const size_t maxOffset = orderedGroups.crbegin()->first; | |
| 187 | 25 | auto iter = orderedGroups.begin(); | |
| 188 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 25 times.
|
63 | for (size_t i = 0; i <= maxOffset; ++i) { |
| 189 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | if (iter->first == i) { |
| 190 |
1/2✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
|
38 | this->addGroupWriteHandle(leaf, iter->second); |
| 191 | ++iter; | ||
| 192 | } | ||
| 193 | else { | ||
| 194 | // empty handle at this index | ||
| 195 | this->addNullGroupHandle(); | ||
| 196 | } | ||
| 197 | } | ||
| 198 | } | ||
| 199 | 1486 | } | |
| 200 | |||
| 201 | inline auto bindValueKernel() | ||
| 202 | { | ||
| 203 | using FunctionTraitsT = codegen::PointKernelAttributeArray::FunctionTraitsT; | ||
| 204 | using ReturnT = FunctionTraitsT::ReturnType; | ||
| 205 | |||
| 206 | 64 | return [&](const openvdb::Coord& origin, void* buffer, bool active, const size_t index) -> ReturnT { | |
| 207 | 64 | mData.mKernelAttributeArray(static_cast<FunctionTraitsT::Arg<0>::Type>(mData.mCustomData), | |
| 208 | reinterpret_cast<FunctionTraitsT::Arg<1>::Type>(origin.data()), | ||
| 209 | static_cast<FunctionTraitsT::Arg<2>::Type>(buffer), | ||
| 210 | static_cast<FunctionTraitsT::Arg<3>::Type>(active), | ||
| 211 | static_cast<FunctionTraitsT::Arg<4>::Type>(index), | ||
| 212 | static_cast<FunctionTraitsT::Arg<5>::Type>(nullptr/*mData.mVoidTransforms.data()*/), | ||
| 213 | static_cast<FunctionTraitsT::Arg<6>::Type>(mHandlesOrBuffers.data()), | ||
| 214 | static_cast<FunctionTraitsT::Arg<7>::Type>(mFlags.data()), | ||
| 215 | 64 | static_cast<FunctionTraitsT::Arg<8>::Type>(mAttributeSet), | |
| 216 | static_cast<FunctionTraitsT::Arg<9>::Type>(mVoidGroupHandles.data()), | ||
| 217 | 64 | static_cast<FunctionTraitsT::Arg<10>::Type>(mLeafLocalData)); | |
| 218 | 120 | }; | |
| 219 | } | ||
| 220 | |||
| 221 | inline auto bindRangeKernel() | ||
| 222 | { | ||
| 223 | using FunctionTraitsT = codegen::PointKernelBufferRange::FunctionTraitsT; | ||
| 224 | using ReturnT = FunctionTraitsT::ReturnType; | ||
| 225 | |||
| 226 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1430 times.
|
1430 | assert(mData.mUseBufferKernel); |
| 227 | |||
| 228 | 1430 | return [&](const openvdb::Coord& origin, void* buffer, Index64* mask, const size_t size) -> ReturnT { | |
| 229 | 1430 | mData.mKernelBufferRange(static_cast<FunctionTraitsT::Arg<0>::Type>(mData.mCustomData), | |
| 230 | reinterpret_cast<FunctionTraitsT::Arg<1>::Type>(origin.data()), | ||
| 231 | static_cast<FunctionTraitsT::Arg<2>::Type>(buffer), | ||
| 232 | static_cast<FunctionTraitsT::Arg<3>::Type>(mask), | ||
| 233 | static_cast<FunctionTraitsT::Arg<4>::Type>(size), | ||
| 234 | static_cast<FunctionTraitsT::Arg<5>::Type>(2/*mData.mIterMode*/), | ||
| 235 | static_cast<FunctionTraitsT::Arg<6>::Type>(nullptr/*mData.mVoidTransforms.data()*/), | ||
| 236 | static_cast<FunctionTraitsT::Arg<7>::Type>(mHandlesOrBuffers.data()), | ||
| 237 | static_cast<FunctionTraitsT::Arg<8>::Type>(mFlags.data()), | ||
| 238 | 1430 | static_cast<FunctionTraitsT::Arg<9>::Type>(mAttributeSet), | |
| 239 | static_cast<FunctionTraitsT::Arg<10>::Type>(mVoidGroupHandles.data()), | ||
| 240 | 1430 | static_cast<FunctionTraitsT::Arg<11>::Type>(mLeafLocalData)); | |
| 241 | 2860 | }; | |
| 242 | } | ||
| 243 | |||
| 244 | template <typename ValueT> | ||
| 245 | 574 | inline void addHandle(LeafT& leaf, const size_t pos) | |
| 246 | { | ||
| 247 | 574 | uint64_t flag = 0; | |
| 248 | const points::AttributeArray& array = leaf.constAttributeArray(pos); | ||
| 249 |
2/2✓ Branch 1 taken 285 times.
✓ Branch 2 taken 2 times.
|
574 | if (array.isUniform()) flag |= uint64_t(1) << 63; |
| 250 | |||
| 251 | // @todo if the array is shared we should probably make it unique? | ||
| 252 | |||
| 253 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
| 254 |
2/2✓ Branch 0 taken 275 times.
✓ Branch 1 taken 12 times.
|
574 | if (mData.mUseBufferKernel) { |
| 255 | 550 | const_cast<points::AttributeArray&>(array).loadData(); | |
| 256 | const char* data = array.constDataAsByteArray(); | ||
| 257 | 550 | void* ptr = static_cast<void*>(const_cast<char*>(data)); | |
| 258 | 550 | mHandlesOrBuffers.emplace_back(ptr); | |
| 259 | const codegen::Codec* codec = | ||
| 260 |
2/4✓ Branch 2 taken 275 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 275 times.
✗ Branch 7 not taken.
|
1100 | codegen::getCodec(ast::tokens::tokenFromTypeString(array.valueType()), array.codecType()); |
| 261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 275 times.
|
550 | if (codec) flag |= codec->flag(); |
| 262 | } | ||
| 263 | else { | ||
| 264 |
1/2✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
24 | typename ReadHandle<ValueT>::UniquePtr handle(new ReadHandle<ValueT>(leaf, Index(pos))); |
| 265 |
1/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
24 | mHandlesOrBuffers.emplace_back(handle->mHandle.get()); |
| 266 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
24 | mAttributeHandles.emplace_back(std::move(handle)); |
| 267 | } | ||
| 268 | #else | ||
| 269 | assert(!mData.mUseBufferKernel); | ||
| 270 | typename ReadHandle<ValueT>::UniquePtr handle(new ReadHandle<ValueT>(leaf, Index(pos))); | ||
| 271 | mHandlesOrBuffers.emplace_back(handle->mHandle.get()); | ||
| 272 | mAttributeHandles.emplace_back(std::move(handle)); | ||
| 273 | #endif | ||
| 274 | |||
| 275 | 574 | mFlags.emplace_back(flag); | |
| 276 | } | ||
| 277 | |||
| 278 | template <typename ValueT> | ||
| 279 | 19726 | inline void addWriteHandle(LeafT& leaf, const size_t pos) | |
| 280 | { | ||
| 281 | 19726 | uint64_t flag = 0; | |
| 282 | 19726 | points::AttributeArray& array = leaf.attributeArray(pos); | |
| 283 | 19726 | array.expand(); | |
| 284 | |||
| 285 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
| 286 |
2/2✓ Branch 0 taken 9491 times.
✓ Branch 1 taken 372 times.
|
19726 | if (mData.mUseBufferKernel) { |
| 287 | 18982 | array.loadData(); | |
| 288 | const char* data = array.constDataAsByteArray(); | ||
| 289 | 18982 | void* ptr = static_cast<void*>(const_cast<char*>(data)); | |
| 290 | 18982 | mHandlesOrBuffers.emplace_back(ptr); | |
| 291 | const codegen::Codec* codec = | ||
| 292 |
2/4✓ Branch 2 taken 9491 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 9491 times.
✗ Branch 7 not taken.
|
37964 | codegen::getCodec(ast::tokens::tokenFromTypeString(array.valueType()), array.codecType()); |
| 293 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 9482 times.
|
18982 | if (codec) flag |= codec->flag(); |
| 294 |
2/4✓ Branch 1 taken 9491 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9491 times.
|
18982 | assert(array.isDataLoaded() && !array.isUniform()); |
| 295 | } | ||
| 296 | else { | ||
| 297 |
1/2✓ Branch 2 taken 168 times.
✗ Branch 3 not taken.
|
744 | typename WriteHandle<ValueT>::UniquePtr handle(new WriteHandle<ValueT>(leaf, Index(pos))); |
| 298 |
1/4✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
744 | mHandlesOrBuffers.emplace_back(handle->mHandle.get()); |
| 299 |
1/2✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
|
744 | mAttributeHandles.emplace_back(std::move(handle)); |
| 300 | } | ||
| 301 | #else | ||
| 302 | assert(!mData.mUseBufferKernel); | ||
| 303 | typename WriteHandle<ValueT>::UniquePtr handle(new WriteHandle<ValueT>(leaf, Index(pos))); | ||
| 304 | mHandlesOrBuffers.emplace_back(handle->mHandle.get()); | ||
| 305 | mAttributeHandles.emplace_back(std::move(handle)); | ||
| 306 | #endif | ||
| 307 | |||
| 308 | 19726 | mFlags.emplace_back(flag); | |
| 309 | } | ||
| 310 | |||
| 311 | inline void addGroupHandle(const LeafT& leaf, const std::string& name) | ||
| 312 | { | ||
| 313 | assert(leaf.attributeSet().descriptor().hasGroup(name)); | ||
| 314 | mGroupHandles.emplace_back(new points::GroupHandle(leaf.groupHandle(name))); | ||
| 315 | mVoidGroupHandles.emplace_back(static_cast<void*>(mGroupHandles.back().get())); | ||
| 316 | } | ||
| 317 | |||
| 318 | 38 | inline void addGroupWriteHandle(LeafT& leaf, const std::string& name) | |
| 319 | { | ||
| 320 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
|
38 | assert(leaf.attributeSet().descriptor().hasGroup(name)); |
| 321 |
1/2✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
|
38 | mGroupHandles.emplace_back(new points::GroupWriteHandle(leaf.groupWriteHandle(name))); |
| 322 | 38 | mVoidGroupHandles.emplace_back(static_cast<void*>(mGroupHandles.back().get())); | |
| 323 | 38 | } | |
| 324 | |||
| 325 | ✗ | inline void addNullGroupHandle() { mVoidGroupHandles.emplace_back(nullptr); } | |
| 326 | |||
| 327 | inline void | ||
| 328 |
1/2✓ Branch 0 taken 10150 times.
✗ Branch 1 not taken.
|
10150 | addAttributeHandle(LeafT& leaf, const std::string& name, const ast::tokens::CoreType type, const bool write) |
| 329 | { | ||
| 330 | // assert so the executer can be marked as noexcept (assuming nothing throws in compute) | ||
| 331 | ✗ | assert(supported(type) && "Could not retrieve attribute handle from unsupported type"); | |
| 332 |
20/22✓ Branch 0 taken 1796 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 136 times.
✓ Branch 3 taken 1172 times.
✓ Branch 4 taken 396 times.
✓ Branch 5 taken 1121 times.
✓ Branch 6 taken 1592 times.
✓ Branch 7 taken 196 times.
✓ Branch 8 taken 196 times.
✓ Branch 9 taken 196 times.
✓ Branch 10 taken 300 times.
✓ Branch 11 taken 493 times.
✓ Branch 12 taken 520 times.
✓ Branch 13 taken 260 times.
✓ Branch 14 taken 264 times.
✓ Branch 15 taken 276 times.
✓ Branch 16 taken 248 times.
✓ Branch 17 taken 276 times.
✓ Branch 18 taken 256 times.
✓ Branch 19 taken 276 times.
✓ Branch 20 taken 180 times.
✗ Branch 21 not taken.
|
10150 | switch (type) { |
| 333 | 1796 | case ast::tokens::BOOL : return this->addAttributeHandleTyped<bool>(leaf, name, write); | |
| 334 | ✗ | case ast::tokens::CHAR : return this->addAttributeHandleTyped<char>(leaf, name, write); | |
| 335 | 136 | case ast::tokens::INT16 : return this->addAttributeHandleTyped<int16_t>(leaf, name, write); | |
| 336 | 1172 | case ast::tokens::INT32 : return this->addAttributeHandleTyped<int32_t>(leaf, name, write); | |
| 337 | 396 | case ast::tokens::INT64 : return this->addAttributeHandleTyped<int64_t>(leaf, name, write); | |
| 338 | 1121 | case ast::tokens::FLOAT : return this->addAttributeHandleTyped<float>(leaf, name, write); | |
| 339 | 1592 | case ast::tokens::DOUBLE : return this->addAttributeHandleTyped<double>(leaf, name, write); | |
| 340 | 196 | case ast::tokens::VEC2I : return this->addAttributeHandleTyped<math::Vec2<int32_t>>(leaf, name, write); | |
| 341 | 196 | case ast::tokens::VEC2F : return this->addAttributeHandleTyped<math::Vec2<float>>(leaf, name, write); | |
| 342 | 196 | case ast::tokens::VEC2D : return this->addAttributeHandleTyped<math::Vec2<double>>(leaf, name, write); | |
| 343 | 300 | case ast::tokens::VEC3I : return this->addAttributeHandleTyped<math::Vec3<int32_t>>(leaf, name, write); | |
| 344 | 493 | case ast::tokens::VEC3F : return this->addAttributeHandleTyped<math::Vec3<float>>(leaf, name, write); | |
| 345 | 520 | case ast::tokens::VEC3D : return this->addAttributeHandleTyped<math::Vec3<double>>(leaf, name, write); | |
| 346 | 260 | case ast::tokens::VEC4I : return this->addAttributeHandleTyped<math::Vec4<int32_t>>(leaf, name, write); | |
| 347 | 264 | case ast::tokens::VEC4F : return this->addAttributeHandleTyped<math::Vec4<float>>(leaf, name, write); | |
| 348 | 276 | case ast::tokens::VEC4D : return this->addAttributeHandleTyped<math::Vec4<double>>(leaf, name, write); | |
| 349 | 248 | case ast::tokens::MAT3F : return this->addAttributeHandleTyped<math::Mat3<float>>(leaf, name, write); | |
| 350 | 276 | case ast::tokens::MAT3D : return this->addAttributeHandleTyped<math::Mat3<double>>(leaf, name, write); | |
| 351 | 256 | case ast::tokens::MAT4F : return this->addAttributeHandleTyped<math::Mat4<float>>(leaf, name, write); | |
| 352 | 276 | case ast::tokens::MAT4D : return this->addAttributeHandleTyped<math::Mat4<double>>(leaf, name, write); | |
| 353 | 180 | case ast::tokens::STRING : return this->addAttributeHandleTyped<std::string>(leaf, name, write); | |
| 354 | case ast::tokens::UNKNOWN : | ||
| 355 | default : return; | ||
| 356 | } | ||
| 357 | } | ||
| 358 | |||
| 359 | private: | ||
| 360 | template <typename ValueType> | ||
| 361 | inline void | ||
| 362 | 20300 | addAttributeHandleTyped(LeafT& leaf, const std::string& name, const bool write) | |
| 363 | { | ||
| 364 | 20300 | const size_t pos = leaf.attributeSet().find(name); | |
| 365 | //assert(!leaf.attributeSet().isShared(pos)); | ||
| 366 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10150 times.
|
20300 | assert(pos != openvdb::points::AttributeSet::INVALID_POS); |
| 367 |
2/2✓ Branch 0 taken 9863 times.
✓ Branch 1 taken 287 times.
|
20300 | if (write) this->addWriteHandle<ValueType>(leaf, pos); |
| 368 | 574 | else this->addHandle<ValueType>(leaf, pos); | |
| 369 | } | ||
| 370 | |||
| 371 | private: | ||
| 372 | const OpData& mData; | ||
| 373 | const points::AttributeSet* const mAttributeSet; | ||
| 374 | std::vector<void*> mHandlesOrBuffers; | ||
| 375 | std::vector<Handles::UniquePtr> mAttributeHandles; | ||
| 376 | std::vector<uint64_t> mFlags; | ||
| 377 | std::vector<void*> mVoidGroupHandles; | ||
| 378 | std::vector<points::GroupHandle::UniquePtr> mGroupHandles; | ||
| 379 | PointLeafLocalData* const mLeafLocalData; | ||
| 380 | }; | ||
| 381 | |||
| 382 | |||
| 383 | /////////////////////////////////////////////////////////////////////////// | ||
| 384 | /////////////////////////////////////////////////////////////////////////// | ||
| 385 | |||
| 386 | |||
| 387 | template<typename FilterT = openvdb::points::NullFilter> | ||
| 388 | struct PointExecuterDeformer | ||
| 389 | { | ||
| 390 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | PointExecuterDeformer(const std::string& positionAttribute, |
| 391 | const FilterT& filter = FilterT()) | ||
| 392 | : mFilter(filter) | ||
| 393 | , mPws(nullptr) | ||
| 394 |
1/4✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | , mPositionAttribute(positionAttribute) {} |
| 395 | |||
| 396 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
|
20 | PointExecuterDeformer(const PointExecuterDeformer& other) |
| 397 | : mFilter(other.mFilter) | ||
| 398 | , mPws(nullptr) | ||
| 399 |
2/8✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
20 | , mPositionAttribute(other.mPositionAttribute) {} |
| 400 | |||
| 401 | template <typename LeafT> | ||
| 402 | 40 | void reset(const LeafT& leaf, const size_t) | |
| 403 | { | ||
| 404 | ✗ | mFilter.reset(leaf); | |
| 405 |
1/2✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
|
40 | mPws.reset(new points::AttributeHandle<Vec3f>(leaf.constAttributeArray(mPositionAttribute))); |
| 406 | } | ||
| 407 | |||
| 408 | template <typename IterT> | ||
| 409 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
56 | void apply(Vec3d& position, const IterT& iter) const |
| 410 | { | ||
| 411 | ✗ | if (mFilter.valid(iter)) { | |
| 412 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
|
56 | assert(mPws); |
| 413 | 56 | position = Vec3d(mPws->get(*iter)); | |
| 414 | } | ||
| 415 | } | ||
| 416 | |||
| 417 | FilterT mFilter; | ||
| 418 | points::AttributeHandle<Vec3f>::UniquePtr mPws; | ||
| 419 | const std::string& mPositionAttribute; | ||
| 420 | }; | ||
| 421 | |||
| 422 | /// @brief VDB Points executer for a compiled function pointer | ||
| 423 | struct PointExecuterOp | ||
| 424 | { | ||
| 425 | using LeafManagerT = openvdb::tree::LeafManager<openvdb::points::PointDataTree>; | ||
| 426 | using LeafNode = openvdb::points::PointDataTree::LeafNodeType; | ||
| 427 | using GroupFilter = openvdb::points::GroupFilter; | ||
| 428 | |||
| 429 | PointExecuterOp(const OpData& data, | ||
| 430 | std::vector<PointLeafLocalData::UniquePtr>& leafLocalData) | ||
| 431 | 748 | : mData(data) | |
| 432 | 748 | , mLeafLocalData(leafLocalData) {} | |
| 433 | |||
| 434 | template<typename FilterT = openvdb::points::NullFilter> | ||
| 435 | inline std::unique_ptr<points::AttributeWriteHandle<Vec3f>> | ||
| 436 | 24 | initPositions(LeafNode& leaf, const FilterT& filter = FilterT()) const | |
| 437 | { | ||
| 438 |
2/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
|
72 | points::AttributeHandle<Vec3f> positions(leaf.constAttributeArray("P")); |
| 439 | std::unique_ptr<points::AttributeWriteHandle<Vec3f>> | ||
| 440 |
3/6✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
|
24 | pws(new points::AttributeWriteHandle<Vec3f>(leaf.attributeArray(mData.mPositionAttribute))); |
| 441 | |||
| 442 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 12 times.
|
60 | for (auto iter = leaf.beginIndexAll(filter); iter; ++iter) { |
| 443 | 36 | const Index idx = *iter; | |
| 444 |
3/6✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
|
36 | const openvdb::Vec3f pos = positions.get(idx) + iter.getCoord().asVec3s(); |
| 445 |
3/8✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
36 | pws->set(idx, mData.mTransform->indexToWorld(pos)); |
| 446 | } | ||
| 447 | |||
| 448 | 24 | return pws; | |
| 449 | } | ||
| 450 | |||
| 451 | 1486 | void operator()(LeafNode& leaf, size_t idx) const | |
| 452 | { | ||
| 453 | 1486 | auto& leafLocalData = mLeafLocalData[idx]; | |
| 454 | 1486 | leafLocalData.reset(new PointLeafLocalData(leaf.getLastValue())); | |
| 455 | |||
| 456 | 1486 | const bool group = mData.mGroupIndex.first != points::AttributeSet::INVALID_POS; | |
| 457 | |||
| 458 | // if we are using position we need to initialise the world space storage | ||
| 459 | 1486 | std::unique_ptr<points::AttributeWriteHandle<Vec3f>> pws; | |
| 460 |
3/4✓ Branch 0 taken 1474 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1474 times.
|
1486 | if (mData.mPositionAccess.first || mData.mPositionAccess.second) { |
| 461 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (group) { |
| 462 | const GroupFilter filter(mData.mGroupIndex); | ||
| 463 | ✗ | pws = this->initPositions(leaf, filter); | |
| 464 | } | ||
| 465 | else { | ||
| 466 |
1/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
12 | pws = this->initPositions(leaf); |
| 467 | } | ||
| 468 | } | ||
| 469 | |||
| 470 |
1/2✓ Branch 1 taken 1486 times.
✗ Branch 2 not taken.
|
2972 | PointFunctionArguments args(mData, leaf, leafLocalData.get()); |
| 471 |
1/2✓ Branch 1 taken 1486 times.
✗ Branch 2 not taken.
|
1486 | void* buffer = static_cast<void*>(leaf.buffer().data()); |
| 472 | |||
| 473 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1478 times.
|
1486 | if (group) { |
| 474 | 8 | const auto kernel = args.bindValueKernel(); | |
| 475 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | const GroupFilter filter(mData.mGroupIndex); |
| 476 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | auto iter = leaf.beginIndex<LeafNode::ValueAllCIter, GroupFilter>(filter); |
| 477 |
4/6✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
12 | for (; iter; ++iter) kernel(leaf.origin(), buffer, /*active*/true, *iter); |
| 478 | } | ||
| 479 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1430 times.
|
1478 | else if (!mData.mUseBufferKernel) { |
| 480 | 48 | const auto kernel = args.bindValueKernel(); | |
| 481 | auto iter = leaf.beginIndexAll(); | ||
| 482 |
4/6✓ Branch 0 taken 60 times.
✓ Branch 1 taken 48 times.
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 60 times.
✗ Branch 8 not taken.
|
108 | for (; iter; ++iter) kernel(leaf.origin(), buffer, /*active*/true, *iter); |
| 483 | } | ||
| 484 | else { | ||
| 485 |
1/2✓ Branch 1 taken 1430 times.
✗ Branch 2 not taken.
|
1430 | const auto kernel = args.bindRangeKernel(); |
| 486 | Index64* masks = &(leaf.getValueMask().template getWord<Index64>(0)); | ||
| 487 |
1/2✓ Branch 1 taken 1430 times.
✗ Branch 2 not taken.
|
1430 | kernel(leaf.origin(), buffer, masks, size_t(LeafNode::NUM_VOXELS)); |
| 488 | } | ||
| 489 | |||
| 490 | // if not writing to position (i.e. post sorting) collapse the temporary attribute | ||
| 491 | |||
| 492 |
4/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1474 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 10 times.
|
1486 | if (pws && !mData.mPositionAccess.second) { |
| 493 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | pws->collapse(); |
| 494 | pws.reset(); | ||
| 495 | } | ||
| 496 | |||
| 497 | // as multiple groups can be stored in a single array, attempt to compact the | ||
| 498 | // arrays directly so that we're not trying to call compact multiple times | ||
| 499 | // unsuccessfully | ||
| 500 |
1/2✓ Branch 1 taken 1486 times.
✗ Branch 2 not taken.
|
1486 | leafLocalData->compact(); |
| 501 | 1486 | } | |
| 502 | |||
| 503 | void operator()(const LeafManagerT::LeafRange& range) const | ||
| 504 | { | ||
| 505 | for (auto leaf = range.begin(); leaf; ++leaf) { | ||
| 506 | (*this)(*leaf, leaf.pos()); | ||
| 507 | } | ||
| 508 | } | ||
| 509 | |||
| 510 | private: | ||
| 511 | const OpData& mData; | ||
| 512 | std::vector<PointLeafLocalData::UniquePtr>& mLeafLocalData; | ||
| 513 | }; | ||
| 514 | |||
| 515 | 92 | inline NamePair typePairFromToken(const ast::tokens::CoreType type) | |
| 516 | { | ||
| 517 |
9/22✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 21 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✓ Branch 11 taken 13 times.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 26 times.
✗ Branch 21 not taken.
|
92 | switch (type) { |
| 518 | ✗ | case ast::tokens::BOOL : return points::TypedAttributeArray<bool>::attributeType(); | |
| 519 | ✗ | case ast::tokens::CHAR : return points::TypedAttributeArray<char>::attributeType(); | |
| 520 | 2 | case ast::tokens::INT16 : return points::TypedAttributeArray<int16_t>::attributeType(); | |
| 521 | 20 | case ast::tokens::INT32 : return points::TypedAttributeArray<int32_t>::attributeType(); | |
| 522 | 2 | case ast::tokens::INT64 : return points::TypedAttributeArray<int64_t>::attributeType(); | |
| 523 | 21 | case ast::tokens::FLOAT : return points::TypedAttributeArray<float>::attributeType(); | |
| 524 | 2 | case ast::tokens::DOUBLE : return points::TypedAttributeArray<double>::attributeType(); | |
| 525 | ✗ | case ast::tokens::VEC2I : return points::TypedAttributeArray<math::Vec2<int32_t>>::attributeType(); | |
| 526 | ✗ | case ast::tokens::VEC2F : return points::TypedAttributeArray<math::Vec2<float>>::attributeType(); | |
| 527 | ✗ | case ast::tokens::VEC2D : return points::TypedAttributeArray<math::Vec2<double>>::attributeType(); | |
| 528 | 4 | case ast::tokens::VEC3I : return points::TypedAttributeArray<math::Vec3<int32_t>>::attributeType(); | |
| 529 | 13 | case ast::tokens::VEC3F : return points::TypedAttributeArray<math::Vec3<float>>::attributeType(); | |
| 530 | 2 | case ast::tokens::VEC3D : return points::TypedAttributeArray<math::Vec3<double>>::attributeType(); | |
| 531 | ✗ | case ast::tokens::VEC4I : return points::TypedAttributeArray<math::Vec4<int32_t>>::attributeType(); | |
| 532 | ✗ | case ast::tokens::VEC4F : return points::TypedAttributeArray<math::Vec4<float>>::attributeType(); | |
| 533 | ✗ | case ast::tokens::VEC4D : return points::TypedAttributeArray<math::Vec4<double>>::attributeType(); | |
| 534 | ✗ | case ast::tokens::MAT3F : return points::TypedAttributeArray<math::Mat3<float>>::attributeType(); | |
| 535 | ✗ | case ast::tokens::MAT3D : return points::TypedAttributeArray<math::Mat3<double>>::attributeType(); | |
| 536 | ✗ | case ast::tokens::MAT4F : return points::TypedAttributeArray<math::Mat4<float>>::attributeType(); | |
| 537 | ✗ | case ast::tokens::MAT4D : return points::TypedAttributeArray<math::Mat4<double>>::attributeType(); | |
| 538 | 26 | case ast::tokens::STRING : return points::StringAttributeArray::attributeType(); | |
| 539 | case ast::tokens::UNKNOWN : | ||
| 540 | default : { | ||
| 541 | return NamePair(); | ||
| 542 | } | ||
| 543 | } | ||
| 544 | } | ||
| 545 | |||
| 546 | 751 | void processAttributes(points::PointDataGrid& grid, | |
| 547 | std::vector<PointAttributeInfo>& attributeInfo, | ||
| 548 | std::pair<bool,bool>& positionAccess, | ||
| 549 | std::string& posWS, | ||
| 550 | const AttributeRegistry& registry, | ||
| 551 | const AttributeBindings& bindings, | ||
| 552 | const bool createMissing, | ||
| 553 | Logger& logger) | ||
| 554 | { | ||
| 555 | const auto leafIter = grid.tree().cbeginLeaf(); | ||
| 556 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 751 times.
|
751 | assert(leafIter); |
| 557 | |||
| 558 | 751 | attributeInfo.reserve(registry.data().size()); | |
| 559 | |||
| 560 | // append attributes | ||
| 561 | |||
| 562 |
2/2✓ Branch 0 taken 5089 times.
✓ Branch 1 taken 749 times.
|
5838 | for (const auto& iter : registry.data()) { |
| 563 | // get the corresponding point attributes | ||
| 564 | const std::string* nameptr = bindings.dataNameBoundTo(iter.name()); | ||
| 565 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5089 times.
|
10087 | if (!nameptr) continue; |
| 566 | const std::string& name = *nameptr; | ||
| 567 | const points::AttributeSet::Descriptor& desc = leafIter->attributeSet().descriptor(); | ||
| 568 | |||
| 569 | // handle position separately as we need to create temp storage during execution | ||
| 570 | // create temporary world space position attribute if P is being accessed | ||
| 571 | // @todo should avoid actually adding this attribute to the tree as its temporary | ||
| 572 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5083 times.
|
5089 | if (name == "P") { |
| 573 | positionAccess = {iter.reads(), iter.writes()}; | ||
| 574 |
3/6✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
|
12 | posWS = desc.uniqueName("__P"); |
| 575 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | points::appendAttribute<openvdb::Vec3f>(grid.tree(), posWS); |
| 576 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | attributeInfo.emplace_back(posWS, ast::tokens::VEC3F, positionAccess.second); |
| 577 | 6 | continue; | |
| 578 | } | ||
| 579 | // add the data name to the attribute info | ||
| 580 |
1/2✓ Branch 1 taken 5083 times.
✗ Branch 2 not taken.
|
5083 | attributeInfo.emplace_back(name, iter.type(), iter.writes()); |
| 581 | |||
| 582 |
1/2✓ Branch 1 taken 5083 times.
✗ Branch 2 not taken.
|
5083 | const size_t pos = desc.find(name); |
| 583 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5081 times.
|
5083 | if (!createMissing && pos == points::AttributeSet::INVALID_POS) { |
| 584 |
6/12✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 2 times.
|
14 | logger.error("Attribute \"" + name + "\" does not exist on grid \"" + grid.getName() + "\"." |
| 585 |
8/14✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✓ Branch 19 taken 1 times.
|
8 | + (name != iter.name() ? "[bound to \"" + iter.name() + " \"]" : "")); |
| 586 | ✗ | continue; | |
| 587 | } | ||
| 588 | |||
| 589 |
2/2✓ Branch 0 taken 4992 times.
✓ Branch 1 taken 89 times.
|
5081 | if (pos != points::AttributeSet::INVALID_POS) { |
| 590 |
1/2✓ Branch 1 taken 4992 times.
✗ Branch 2 not taken.
|
4992 | const points::AttributeArray* const array = leafIter->attributeSet().getConst(pos); |
| 591 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4992 times.
|
4992 | assert(array); |
| 592 |
2/4✓ Branch 1 taken 4992 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4992 times.
|
4992 | if (array->stride() > 1) { |
| 593 | ✗ | logger.warning("Attribute \"" + name + (name != iter.name() ? "\" [bound to \"" + iter.name() + "\"]" : "\"") | |
| 594 | ✗ | + " on grid \"" + grid.getName() + "\"is a strided (array) attribute. " | |
| 595 | ✗ | "Reading or writing to this attribute with @" + name + " will only access the first element."); | |
| 596 | } | ||
| 597 | |||
| 598 |
1/2✓ Branch 1 taken 4992 times.
✗ Branch 2 not taken.
|
4992 | const NamePair& type = desc.type(pos); |
| 599 | const ast::tokens::CoreType typetoken = | ||
| 600 | 4992 | ast::tokens::tokenFromTypeString(type.first); | |
| 601 | |||
| 602 |
3/4✓ Branch 0 taken 64 times.
✓ Branch 1 taken 4928 times.
✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
|
5056 | if (typetoken != iter.type() && |
| 603 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 64 times.
|
128 | !(type.second == "str" && iter.type() == ast::tokens::STRING)) { |
| 604 | ✗ | logger.error("Mismatching attributes types. Attribute \"" + name + | |
| 605 | ✗ | (name != iter.name() ? "\" [bound to \"" + iter.name() + "\"]" : "\"") + | |
| 606 | ✗ | " on grid \"" + grid.getName() + "\" exists of type \"" + type.first + | |
| 607 | ✗ | "\" but has been accessed with type \"" + | |
| 608 | ✗ | ast::tokens::typeStringFromToken(iter.type()) + "\""); | |
| 609 | } | ||
| 610 | 4992 | continue; | |
| 611 | } | ||
| 612 | |||
| 613 | ✗ | assert(supported(iter.type())); | |
| 614 |
1/2✓ Branch 1 taken 89 times.
✗ Branch 2 not taken.
|
178 | const NamePair type = typePairFromToken(iter.type()); |
| 615 |
1/2✓ Branch 1 taken 89 times.
✗ Branch 2 not taken.
|
89 | points::appendAttribute(grid.tree(), name, type); |
| 616 | } | ||
| 617 | 749 | } | |
| 618 | |||
| 619 | 749 | bool checkCodecs(const points::AttributeSet::Descriptor& desc, | |
| 620 | const AttributeRegistry& registry, | ||
| 621 | const AttributeBindings& bindings, | ||
| 622 | const std::string& posWS) | ||
| 623 | { | ||
| 624 |
2/2✓ Branch 0 taken 4999 times.
✓ Branch 1 taken 725 times.
|
5724 | for (const auto& iter : registry.data()) { |
| 625 | // no support for strings yet (we should just use the cbind) | ||
| 626 |
2/2✓ Branch 0 taken 4975 times.
✓ Branch 1 taken 24 times.
|
4999 | if (iter.type() == ast::tokens::STRING) return false; |
| 627 | |||
| 628 | // if this type has no possible codec, continue | ||
| 629 |
1/2✓ Branch 1 taken 4975 times.
✗ Branch 2 not taken.
|
4975 | const auto* codecs = codegen::getTypeSupportedCodecs(iter.type()); |
| 630 |
2/2✓ Branch 0 taken 4151 times.
✓ Branch 1 taken 824 times.
|
5780 | if (!codecs) continue; |
| 631 | |||
| 632 |
1/2✓ Branch 1 taken 824 times.
✗ Branch 2 not taken.
|
824 | std::string name = iter.name(); |
| 633 | const std::string* nameptr = bindings.dataNameBoundTo(name); | ||
| 634 |
1/2✓ Branch 0 taken 824 times.
✗ Branch 1 not taken.
|
824 | if (nameptr) name = *nameptr; |
| 635 | ✗ | else if (name == "P") name = posWS; | |
| 636 | |||
| 637 |
2/4✓ Branch 1 taken 824 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 824 times.
✗ Branch 5 not taken.
|
824 | const std::string& codec = desc.type(desc.find(name)).second; |
| 638 | |||
| 639 | // null codecs can be ignored | ||
| 640 |
3/4✓ Branch 1 taken 824 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 805 times.
✓ Branch 5 taken 19 times.
|
824 | if (codec == std::string(points::NullCodec::name())) continue; |
| 641 | |||
| 642 | // unknown codec in use, fall back to cbinding | ||
| 643 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
|
19 | if (codecs->find(codec) == codecs->cend()) return false; |
| 644 | } | ||
| 645 | |||
| 646 | 725 | return true; | |
| 647 | } | ||
| 648 | |||
| 649 | } // anonymous namespace | ||
| 650 | |||
| 651 | 757 | PointExecutable::PointExecutable(const std::shared_ptr<const llvm::LLVMContext>& context, | |
| 652 | const std::shared_ptr<const llvm::ExecutionEngine>& engine, | ||
| 653 | const AttributeRegistry::ConstPtr& attributeRegistry, | ||
| 654 | const CustomData::ConstPtr& customData, | ||
| 655 | const std::unordered_map<std::string, uint64_t>& functions, | ||
| 656 | 757 | const ast::Tree& ast) | |
| 657 | : mContext(context) | ||
| 658 | , mExecutionEngine(engine) | ||
| 659 | , mAttributeRegistry(attributeRegistry) | ||
| 660 | , mCustomData(customData) | ||
| 661 | , mFunctionAddresses(functions) | ||
| 662 |
2/4✓ Branch 1 taken 757 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 757 times.
✗ Branch 5 not taken.
|
757 | , mSettings(new Settings) |
| 663 | { | ||
| 664 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 757 times.
|
757 | assert(mContext); |
| 665 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 757 times.
|
757 | assert(mExecutionEngine); |
| 666 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 757 times.
|
757 | assert(mAttributeRegistry); |
| 667 | |||
| 668 | // parse the AST for known functions which require pre/post processing | ||
| 669 |
2/4✓ Branch 1 taken 757 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 757 times.
✗ Branch 5 not taken.
|
757 | mSettings->mPostDelete = ast::callsFunction(ast, "deletepoint"); |
| 670 | |||
| 671 | // Set up the default attribute bindings | ||
| 672 |
2/2✓ Branch 0 taken 5085 times.
✓ Branch 1 taken 757 times.
|
5842 | for (const auto& iter : mAttributeRegistry->data()) { |
| 673 |
1/2✓ Branch 1 taken 5085 times.
✗ Branch 2 not taken.
|
5085 | mSettings->mBindings.set(iter.name(), iter.name()); |
| 674 | } | ||
| 675 | 757 | } | |
| 676 | |||
| 677 | ✗ | PointExecutable::PointExecutable(const PointExecutable& other) | |
| 678 | : mContext(other.mContext) | ||
| 679 | , mExecutionEngine(other.mExecutionEngine) | ||
| 680 | , mAttributeRegistry(other.mAttributeRegistry) | ||
| 681 | , mCustomData(other.mCustomData) | ||
| 682 | , mFunctionAddresses(other.mFunctionAddresses) | ||
| 683 | ✗ | , mSettings(new Settings(*other.mSettings)) { | |
| 684 | } | ||
| 685 | |||
| 686 | 757 | PointExecutable::~PointExecutable() {} | |
| 687 | |||
| 688 | 751 | void PointExecutable::execute(openvdb::points::PointDataGrid& grid) const | |
| 689 | { | ||
| 690 | using LeafManagerT = openvdb::tree::LeafManager<openvdb::points::PointDataTree>; | ||
| 691 | |||
| 692 | Logger* logger; | ||
| 693 | 748 | std::unique_ptr<Logger> log; | |
| 694 | if (true) { | ||
| 695 | /// @note This branch exists for forwards compatibility with upcoming | ||
| 696 | /// changes to allow a logger to be provided to the executables | ||
| 697 |
3/8✓ Branch 3 taken 751 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 751 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
|
3007 | log.reset(new Logger([](const std::string& error) { |
| 698 |
1/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
12 | OPENVDB_THROW(AXExecutionError, error); |
| 699 |
2/4✓ Branch 1 taken 751 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 751 times.
✗ Branch 5 not taken.
|
751 | })); |
| 700 | logger = log.get(); | ||
| 701 | } | ||
| 702 | |||
| 703 | const auto leafIter = grid.tree().cbeginLeaf(); | ||
| 704 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 751 times.
|
751 | if (!leafIter) { |
| 705 |
0/8✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
3 | logger->warning("PointDataGrid \"" + grid.getName() + "\" is empty."); |
| 706 | ✗ | return; | |
| 707 | } | ||
| 708 | |||
| 709 | // Initialize the shared op data | ||
| 710 | 748 | OpData data; | |
| 711 | |||
| 712 | // create any missing attributes and handle temp ws position storage | ||
| 713 | data.mPositionAccess = {false, false}; | ||
| 714 | 751 | processAttributes(grid, data.mAttributeInfo, data.mPositionAccess, data.mPositionAttribute, | |
| 715 | 751 | *mAttributeRegistry, mSettings->mBindings, | |
| 716 |
2/2✓ Branch 1 taken 749 times.
✓ Branch 2 taken 2 times.
|
751 | mSettings->mCreateMissing, *logger); |
| 717 | |||
| 718 | 749 | data.mKernelAttributeArray = | |
| 719 | reinterpret_cast<KernelValueFunctionPtr> | ||
| 720 |
2/4✓ Branch 1 taken 749 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 749 times.
✗ Branch 5 not taken.
|
1498 | (mFunctionAddresses.at(codegen::PointKernelAttributeArray::getDefaultName())); |
| 721 | 749 | data.mKernelBufferRange = | |
| 722 | reinterpret_cast<KernelBufferRangeFunctionPtr> | ||
| 723 |
4/6✓ Branch 1 taken 749 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 749 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 745 times.
|
1498 | (mFunctionAddresses.at(codegen::PointKernelBufferRange::getDefaultName())); |
| 724 | 749 | data.mTransform = &grid.transform(); | |
| 725 | 749 | data.mCustomData = mCustomData.get(); | |
| 726 | 749 | data.mGroupIndex.first = openvdb::points::AttributeSet::INVALID_POS; | |
| 727 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 745 times.
|
749 | data.mAttributeRegistry = mAttributeRegistry.get(); |
| 728 | //data.mPositionAccess = mAttributeRegistry->accessPattern("P", ast::tokens::VEC3F); | ||
| 729 | |||
| 730 | // init the internal dead group if necessary | ||
| 731 | |||
| 732 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 745 times.
|
749 | if (mSettings->mPostDelete) { |
| 733 | // @todo This group is hard coded in the deletepoint function call - we | ||
| 734 | // should perhaps instead pass in a unique group string to the point kernel | ||
| 735 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
|
8 | if (leafIter->attributeSet().descriptor().hasGroup("__ax_dead")) { |
| 736 | ✗ | logger->warning("Input points grid \"" + grid.getName() + "\" contains the " | |
| 737 | "internal point group \"__ax_dead\" which is used for deleting points. " | ||
| 738 | "points in this group may also be removed."); | ||
| 739 | } | ||
| 740 | else { | ||
| 741 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
8 | points::appendGroup(grid.tree(), "__ax_dead"); |
| 742 | } | ||
| 743 | } | ||
| 744 | |||
| 745 | const bool usingGroup = !mSettings->mGroup.empty(); | ||
| 746 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 746 times.
|
749 | if (usingGroup) { |
| 747 |
3/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
|
3 | if (!leafIter->attributeSet().descriptor().hasGroup(mSettings->mGroup)) { |
| 748 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
|
4 | logger->error("Requested point group \"" + mSettings->mGroup + |
| 749 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
7 | "\" on grid \"" + grid.getName() + "\" does not exist."); |
| 750 | } | ||
| 751 | else { | ||
| 752 | data.mGroupIndex = | ||
| 753 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | leafIter->attributeSet().groupIndex(mSettings->mGroup); |
| 754 | } | ||
| 755 | } | ||
| 756 | |||
| 757 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 748 times.
|
748 | if (logger->hasError()) return; |
| 758 | |||
| 759 | // Compute whether we can use the accelerated kernel | ||
| 760 | // @note Assumes attributes are valid (i.e. has errored out if they are not) | ||
| 761 | |||
| 762 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
| 763 |
2/2✓ Branch 0 taken 746 times.
✓ Branch 1 taken 2 times.
|
748 | if (!usingGroup) { |
| 764 | const auto& desc = leafIter->attributeSet().descriptor(); | ||
| 765 | 746 | data.mUseBufferKernel = checkCodecs(desc, *mAttributeRegistry, | |
| 766 |
1/2✓ Branch 1 taken 746 times.
✗ Branch 2 not taken.
|
746 | mSettings->mBindings, |
| 767 | data.mPositionAttribute); | ||
| 768 | } | ||
| 769 | else { | ||
| 770 | // if a group has been specified we can't use the buffer range yet | ||
| 771 | 2 | data.mUseBufferKernel = false; | |
| 772 | } | ||
| 773 | #else | ||
| 774 | // can't access data buffers until ABI >= 9 | ||
| 775 | data.mUseBufferKernel = false; | ||
| 776 | #endif | ||
| 777 | |||
| 778 | // execute | ||
| 779 | |||
| 780 |
1/2✓ Branch 1 taken 748 times.
✗ Branch 2 not taken.
|
1496 | LeafManagerT leafManager(grid.tree()); |
| 781 |
2/4✓ Branch 1 taken 748 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 748 times.
✗ Branch 5 not taken.
|
1496 | std::vector<PointLeafLocalData::UniquePtr> leafLocalData(leafManager.leafCount()); |
| 782 | 748 | const bool threaded = mSettings->mGrainSize > 0; | |
| 783 | |||
| 784 | PointExecuterOp executerOp(data, leafLocalData); | ||
| 785 |
1/2✓ Branch 1 taken 748 times.
✗ Branch 2 not taken.
|
748 | leafManager.foreach(executerOp, threaded, mSettings->mGrainSize); |
| 786 | |||
| 787 | // Check to see if any new data has been added and apply it accordingly | ||
| 788 | |||
| 789 | std::set<std::string> groups; | ||
| 790 | bool newStrings = false; | ||
| 791 | |||
| 792 | { | ||
| 793 | points::StringMetaInserter | ||
| 794 |
2/4✓ Branch 1 taken 748 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 748 times.
✗ Branch 5 not taken.
|
1496 | inserter(leafIter->attributeSet().descriptorPtr()->getMetadata()); |
| 795 |
2/2✓ Branch 0 taken 1486 times.
✓ Branch 1 taken 748 times.
|
2234 | for (const auto& leafData : leafLocalData) { |
| 796 |
1/2✓ Branch 1 taken 1486 times.
✗ Branch 2 not taken.
|
1486 | leafData->getGroups(groups); |
| 797 |
1/2✓ Branch 1 taken 1486 times.
✗ Branch 2 not taken.
|
1486 | newStrings |= leafData->insertNewStrings(inserter); |
| 798 | } | ||
| 799 | } | ||
| 800 | |||
| 801 | // append and copy over newly created groups | ||
| 802 | // @todo We should just be able to steal the arrays and compact | ||
| 803 | // groups but the API for this isn't very nice at the moment | ||
| 804 | |||
| 805 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 748 times.
|
759 | for (const auto& name : groups) { |
| 806 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | points::appendGroup(grid.tree(), name); |
| 807 | } | ||
| 808 | |||
| 809 | // add new groups and set strings | ||
| 810 | |||
| 811 |
1/2✓ Branch 1 taken 748 times.
✗ Branch 2 not taken.
|
748 | leafManager.foreach( |
| 812 | 1486 | [&groups, &leafLocalData, newStrings] (auto& leaf, size_t idx) { | |
| 813 | |||
| 814 | PointLeafLocalData::UniquePtr& leafData = leafLocalData[idx]; | ||
| 815 | |||
| 816 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 1486 times.
|
1499 | for (const auto& name : groups) { |
| 817 | |||
| 818 | // Attempt to get the group handle out of the leaf local data form this | ||
| 819 | // leaf. This may not exist as although all of the unique set are appended | ||
| 820 | // to the tree (above), not every leaf may have been directly touched | ||
| 821 | // by every new group. Some leaf nodes may not require any bit mask copying | ||
| 822 | |||
| 823 | 13 | points::GroupWriteHandle* tmpHandle = leafData->get(name); | |
| 824 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!tmpHandle) continue; |
| 825 | |||
| 826 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
13 | points::GroupWriteHandle handle = leaf.groupWriteHandle(name); |
| 827 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 1 times.
|
13 | if (tmpHandle->isUniform()) { |
| 828 |
2/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
|
12 | handle.collapse(tmpHandle->get(0)); |
| 829 | } | ||
| 830 | else { | ||
| 831 | const openvdb::Index size = tmpHandle->size(); | ||
| 832 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
5 | for (openvdb::Index i = 0; i < size; ++i) { |
| 833 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | handle.set(i, tmpHandle->get(i)); |
| 834 | } | ||
| 835 | } | ||
| 836 | } | ||
| 837 | |||
| 838 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1438 times.
|
1486 | if (newStrings) { |
| 839 | 48 | const MetaMap& metadata = leaf.attributeSet().descriptor().getMetadata(); | |
| 840 | const PointLeafLocalData::StringArrayMap& stringArrayMap = leafData->getStringArrayMap(); | ||
| 841 | |||
| 842 |
2/2✓ Branch 0 taken 148 times.
✓ Branch 1 taken 48 times.
|
196 | for (const auto& arrayIter : stringArrayMap) { |
| 843 | 148 | points::StringAttributeWriteHandle::Ptr handle = | |
| 844 |
1/2✓ Branch 1 taken 148 times.
✗ Branch 2 not taken.
|
148 | points::StringAttributeWriteHandle::create(*(arrayIter.first), metadata); |
| 845 | |||
| 846 |
2/2✓ Branch 0 taken 185 times.
✓ Branch 1 taken 148 times.
|
333 | for (const auto& iter : arrayIter.second) { |
| 847 |
1/2✓ Branch 1 taken 185 times.
✗ Branch 2 not taken.
|
185 | handle->set(static_cast<Index>(iter.first), iter.second); |
| 848 | } | ||
| 849 | } | ||
| 850 | } | ||
| 851 | 1486 | }, threaded, mSettings->mGrainSize); | |
| 852 | |||
| 853 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 744 times.
|
748 | if (data.mPositionAccess.second) { |
| 854 | // if position is writable, sort the points | ||
| 855 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (usingGroup) { |
| 856 | openvdb::points::GroupFilter filter(data.mGroupIndex); | ||
| 857 | ✗ | PointExecuterDeformer<openvdb::points::GroupFilter> deformer(data.mPositionAttribute, filter); | |
| 858 | ✗ | openvdb::points::movePoints(grid, deformer); | |
| 859 | } | ||
| 860 | else { | ||
| 861 | PointExecuterDeformer<> deformer(data.mPositionAttribute); | ||
| 862 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
4 | openvdb::points::movePoints(grid, deformer); |
| 863 | } | ||
| 864 | } | ||
| 865 | |||
| 866 |
3/4✓ Branch 0 taken 742 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 742 times.
|
748 | if (data.mPositionAccess.first || data.mPositionAccess.second) { |
| 867 | // remove temporary world space storage | ||
| 868 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | points::dropAttribute(grid.tree(), data.mPositionAttribute); |
| 869 | } | ||
| 870 | |||
| 871 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 744 times.
|
748 | if (mSettings->mPostDelete) { |
| 872 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
8 | points::deleteFromGroup(grid.tree(), "__ax_dead", false, /*drop=*/true); |
| 873 | } | ||
| 874 | } | ||
| 875 | |||
| 876 | |||
| 877 | ///////////////////////////////////////////// | ||
| 878 | ///////////////////////////////////////////// | ||
| 879 | |||
| 880 | |||
| 881 | 725 | void PointExecutable::setCreateMissing(const bool flag) | |
| 882 | { | ||
| 883 | 725 | mSettings->mCreateMissing = flag; | |
| 884 | 725 | } | |
| 885 | |||
| 886 | ✗ | bool PointExecutable::getCreateMissing() const | |
| 887 | { | ||
| 888 | ✗ | return mSettings->mCreateMissing; | |
| 889 | } | ||
| 890 | |||
| 891 | // void PointExecutable::setValueIterator(const PointExecutable::IterType& iter) | ||
| 892 | // { | ||
| 893 | // mSettings->mValueIterator = iter; | ||
| 894 | // } | ||
| 895 | |||
| 896 | // PointExecutable::IterType PointExecutable::getValueIterator() const | ||
| 897 | // { | ||
| 898 | // return mSettings->mValueIterator; | ||
| 899 | // } | ||
| 900 | |||
| 901 | ✗ | void PointExecutable::setGrainSize(const size_t grain) | |
| 902 | { | ||
| 903 | ✗ | mSettings->mGrainSize = grain; | |
| 904 | } | ||
| 905 | |||
| 906 | ✗ | size_t PointExecutable::getGrainSize() const | |
| 907 | { | ||
| 908 | ✗ | return mSettings->mGrainSize; | |
| 909 | } | ||
| 910 | |||
| 911 | 1 | void PointExecutable::setGroupExecution(const std::string& group) | |
| 912 | { | ||
| 913 | 1 | mSettings->mGroup = group; | |
| 914 | 1 | } | |
| 915 | |||
| 916 | ✗ | const std::string& PointExecutable::getGroupExecution() const | |
| 917 | { | ||
| 918 | ✗ | return mSettings->mGroup; | |
| 919 | } | ||
| 920 | |||
| 921 | 19 | void PointExecutable::setAttributeBindings(const AttributeBindings& bindings) | |
| 922 | { | ||
| 923 | //@todo: warn when inferred P, Cd, N etc are bound they default to vec3f | ||
| 924 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 19 times.
|
38 | for (const auto& binding : bindings.axToDataMap()) { |
| 925 | 19 | mSettings->mBindings.set(binding.first, binding.second); | |
| 926 | } | ||
| 927 | |||
| 928 | // check the registry to make sure everything is bound | ||
| 929 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 18 times.
|
53 | for (const auto& access : mAttributeRegistry->data()) { |
| 930 | if (!mSettings->mBindings.isBoundAXName(access.name())) { | ||
| 931 | if (bindings.isBoundDataName(access.name())) { | ||
| 932 |
6/14✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
|
8 | OPENVDB_THROW(AXExecutionError, "AX attribute \"@" |
| 933 | + access.name() + "\" not bound to any point attribute." | ||
| 934 | " Point attribute \"" + access.name() + "\" bound to \"@" | ||
| 935 | + *bindings.axNameBoundTo(access.name()) + "\"."); | ||
| 936 | } | ||
| 937 | else { | ||
| 938 | // rebind to itself as it may have been unbound | ||
| 939 | // by a previous set call | ||
| 940 | 1 | mSettings->mBindings.set(access.name(), access.name()); | |
| 941 | } | ||
| 942 | } | ||
| 943 | } | ||
| 944 | 18 | } | |
| 945 | |||
| 946 | 1 | const AttributeBindings& PointExecutable::getAttributeBindings() const | |
| 947 | { | ||
| 948 | 1 | return mSettings->mBindings; | |
| 949 | } | ||
| 950 | |||
| 951 | // | ||
| 952 | |||
| 953 | 3 | bool PointExecutable::usesAcceleratedKernel(const points::PointDataTree& tree) const | |
| 954 | { | ||
| 955 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (tree.empty()) return true; |
| 956 | |||
| 957 | // deep copy the Descriptor | ||
| 958 | |||
| 959 | const auto leafIter = tree.cbeginLeaf(); | ||
| 960 | points::AttributeSet::Descriptor::Ptr desc( | ||
| 961 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | new points::AttributeSet::Descriptor(leafIter->attributeSet().descriptor())); |
| 962 | |||
| 963 | // add any attributes which don't exist for the codec check | ||
| 964 | |||
| 965 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 3 times.
|
18 | for (const auto& iter : mAttributeRegistry->data()) { |
| 966 | // get the corresponding point attributes | ||
| 967 | const std::string* nameptr = mSettings->mBindings.dataNameBoundTo(iter.name()); | ||
| 968 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | if (!nameptr) continue; |
| 969 | const std::string& name = *nameptr; | ||
| 970 |
2/4✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
|
15 | if (points::AttributeSet::INVALID_POS == desc->find(name)) { |
| 971 | ✗ | const NamePair type = typePairFromToken(iter.type()); | |
| 972 | ✗ | desc = desc->duplicateAppend(name, type); | |
| 973 | } | ||
| 974 | } | ||
| 975 | |||
| 976 | // If P is being written or read from it is implicitly converted | ||
| 977 | // to an uncompressed attribute, so make sure P is not compressed | ||
| 978 | |||
| 979 |
6/12✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
9 | desc = desc->duplicateDrop({desc->find("P")}); |
| 980 |
3/8✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
6 | desc = desc->duplicateAppend("P", typePairFromToken(ast::tokens::CoreType::VEC3F)); |
| 981 | |||
| 982 |
3/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
6 | return checkCodecs(*desc, *mAttributeRegistry, |
| 983 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | mSettings->mBindings, "P"); |
| 984 | } | ||
| 985 | |||
| 986 | |||
| 987 | } // namespace ax | ||
| 988 | } // namespace OPENVDB_VERSION_NAME | ||
| 989 | } // namespace openvdb | ||
| 990 | |||
| 991 |