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