1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 //
4 /// @file VectorTransformer.h
5
6 #ifndef OPENVDB_TOOLS_VECTORTRANSFORMER_HAS_BEEN_INCLUDED
7 #define OPENVDB_TOOLS_VECTORTRANSFORMER_HAS_BEEN_INCLUDED
8
9 #include <openvdb/Types.h>
10 #include <openvdb/math/Mat4.h>
11 #include <openvdb/math/Vec3.h>
12 #include <openvdb/openvdb.h>
13 #include "ValueTransformer.h" // for tools::foreach()
14 #include <type_traits>
15
16
17 namespace openvdb {
18 OPENVDB_USE_VERSION_NAMESPACE
19 namespace OPENVDB_VERSION_NAME {
20 namespace tools {
21
22 /// @brief Apply an affine transform to the voxel values of a vector-valued grid
23 /// in accordance with the grid's vector type (covariant, contravariant, etc.).
24 /// @throw TypeError if the grid is not vector-valued
25 template<typename GridType>
26 void
27 transformVectors(GridType&, const Mat4d&);
28
29
30 ////////////////////////////////////////
31
32
33 // Functors for use with tools::foreach() to transform vector voxel values
34
35 struct HomogeneousMatMul
36 {
37 const Mat4d mat;
HomogeneousMatMulHomogeneousMatMul38 HomogeneousMatMul(const Mat4d& _mat): mat(_mat) {}
operatorHomogeneousMatMul39 template<typename TreeIterT> void operator()(const TreeIterT& it) const
40 {
41 Vec3d v(*it);
42 it.setValue(mat.transformH(v));
43 }
44 };
45
46 struct MatMul
47 {
48 const Mat4d mat;
MatMulMatMul49 MatMul(const Mat4d& _mat): mat(_mat) {}
50 template<typename TreeIterT>
operatorMatMul51 void operator()(const TreeIterT& it) const
52 {
53 Vec3d v(*it);
54 it.setValue(mat.transform3x3(v));
55 }
56 };
57
58 struct MatMulNormalize
59 {
60 const Mat4d mat;
MatMulNormalizeMatMulNormalize61 MatMulNormalize(const Mat4d& _mat): mat(_mat) {}
62 template<typename TreeIterT>
operatorMatMulNormalize63 void operator()(const TreeIterT& it) const
64 {
65 Vec3d v(*it);
66 v = mat.transform3x3(v);
67 v.normalize();
68 it.setValue(v);
69 }
70 };
71
72
73 //{
74 /// @cond OPENVDB_DOCS_INTERNAL
75
76 /// @internal This overload is enabled only for scalar-valued grids.
77 template<typename GridType> inline
78 typename std::enable_if<!VecTraits<typename GridType::ValueType>::IsVec, void>::type
doTransformVectors(GridType &,const Mat4d &)79 doTransformVectors(GridType&, const Mat4d&)
80 {
81 OPENVDB_THROW(TypeError, "tools::transformVectors() requires a vector-valued grid");
82 }
83
84 /// @internal This overload is enabled only for vector-valued grids.
85 template<typename GridType> inline
86 typename std::enable_if<VecTraits<typename GridType::ValueType>::IsVec, void>::type
doTransformVectors(GridType & grid,const Mat4d & mat)87 doTransformVectors(GridType& grid, const Mat4d& mat)
88 {
89 if (!grid.isInWorldSpace()) return;
90
91 const VecType vecType = grid.getVectorType();
92 switch (vecType) {
93 case VEC_COVARIANT:
94 case VEC_COVARIANT_NORMALIZE:
95 {
96 Mat4d invmat = mat.inverse();
97 invmat = invmat.transpose();
98
99 if (vecType == VEC_COVARIANT_NORMALIZE) {
100 foreach(grid.beginValueAll(), MatMulNormalize(invmat));
101 } else {
102 foreach(grid.beginValueAll(), MatMul(invmat));
103 }
104 break;
105 }
106
107 case VEC_CONTRAVARIANT_RELATIVE:
108 foreach(grid.beginValueAll(), MatMul(mat));
109 break;
110
111 case VEC_CONTRAVARIANT_ABSOLUTE:
112 foreach(grid.beginValueAll(), HomogeneousMatMul(mat));
113 break;
114
115 case VEC_INVARIANT:
116 break;
117 }
118 }
119
120 /// @endcond
121 //}
122
123
124 template<typename GridType>
125 void
transformVectors(GridType & grid,const Mat4d & mat)126 transformVectors(GridType& grid, const Mat4d& mat)
127 {
128 doTransformVectors<GridType>(grid, mat);
129 }
130
131
132 ////////////////////////////////////////
133
134
135 // Explicit Template Instantiation
136
137 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
138
139 #ifdef OPENVDB_INSTANTIATE_VECTORTRANSFORMER
140 #include <openvdb/util/ExplicitInstantiation.h>
141 #endif
142
143 #define _FUNCTION(TreeT) \
144 void transformVectors(Grid<TreeT>&, const Mat4d&)
145 OPENVDB_VEC3_TREE_INSTANTIATE(_FUNCTION)
146 #undef _FUNCTION
147
148 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
149
150
151 } // namespace tools
152 } // namespace OPENVDB_VERSION_NAME
153 } // namespace openvdb
154
155 #endif // OPENVDB_TOOLS_VECTORTRANSFORMER_HAS_BEEN_INCLUDED
156