HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GA_AttributeTransformer.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: GA_AttributeTransformer.h ( GA Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __GA_Transform__
12 #define __GA_Transform__
13 
14 #include "GA_API.h"
15 
16 #include "GA_Handle.h"
17 #include "GA_PageHandle.h"
18 #include "GA_Range.h" // for GA_Range
19 #include "GA_Types.h" // for GA_Offset, etc
20 
21 #include <UT/UT_Array.h> // for UT_Array
22 #include <UT/UT_Matrix3.h> // for UT_Matrix3T
23 #include <UT/UT_Matrix4.h>
24 #include <UT/UT_Quaternion.h>
25 
26 #include <SYS/SYS_Types.h> // for fpreal32, fpreal64, exint
27 
28 
29 class GA_AIFMath;
30 class GA_AIFTuple;
31 class GA_Attribute;
32 class GA_AttributeFilter;
33 class GA_Detail;
34 
35 
36 /// @brief Class to efficiently transform multiple attributes
37 ///
38 /// This class will transform attributes as efficiently as possible, depending
39 /// on the attribute's properties. The transformer works on a single class of
40 /// attributes (i.e. GA_ATTRIB_POINT).
42 {
43 public:
44  /// @brief Class to pass transforms to GA_AttributeTransformer
45  ///
46  /// Computing inverse/quaternion transforms can be expensive. If possible,
47  /// you should reuse unchanging Transform objects rather than re-building
48  /// them when performing multiple transforms.
49  template <typename FLOAT_T>
50  class Transform
51  {
52  public:
53  typedef FLOAT_T ValueType;
55  : myM()
56  , myHasI(false)
57  , myHasQ(false)
58  {
59  }
60  template<typename FLOAT_T2>
62  : myM(m)
63  , myHasI(false)
64  , myHasQ(false)
65  {
66  }
67  /// Set the matrix
68  template<typename FLOAT_T2>
69  void set(const UT_Matrix4T<FLOAT_T2> &m)
70  {
71  myM = m;
72  myHasI = false;
73  myHasQ = false;
74  }
75  /// Compute the inverse (if required)
77  {
78  if (!myHasI)
79  {
80  UT_Matrix3T<FLOAT_T> m3(myM);
81  myM.invert(myIM);
82  if (m3.determinant() < 0)
83  myIM.scale(-1, -1, -1);
84  myHasI = true;
85  }
86  }
87  /// Compute the quaternion transform (if required)
89  {
90  if (!myHasQ)
91  {
92  UT_Matrix3T<FLOAT_T> m3(myM);
93  myQ.updateFromArbitraryMatrix(m3);
94  myHasQ = true;
95  }
96  }
97 
98  /// @{
99  /// Accessor
100  const UT_Matrix4T<FLOAT_T> &xform() const { return myM; }
101  const UT_Matrix4T<FLOAT_T> &ixform() const { return myIM; }
102  const UT_QuaternionT<FLOAT_T> &q() const { return myQ; }
103  /// @}
104 
105  private:
109  bool myHasI;
110  bool myHasQ;
111  };
112 
113  /// @brief Handle to a transformable attribute
115  {
116  public:
117  /// @{
118  /// Handle callback functions. These perform different styles of
119  /// transformation depending on the attribute type properties.
120  typedef void (*GAtransformPageF)(const Handle &handle,
121  const Transform<fpreal32> &context,
123  typedef void (*GAtransformPageD)(const Handle &handle,
124  const Transform<fpreal64> &context,
126  typedef void (*GAtransformF)(const Handle &handle,
127  const Transform<fpreal32> &context,
128  GA_Offset offset);
129  typedef void (*GAtransformD)(const Handle &handle,
130  const Transform<fpreal64> &context,
131  GA_Offset offset);
132  /// @}
133 
134  /// Construct a handle for a given attribute
135  Handle(GA_Attribute *attrib, bool keep_length = false);
136  ~Handle() { }
137 
138  /// @{
139  /// Transform the attribute using the handle callback
141  GA_Offset start, GA_Offset end) const
142  { myTransformPageF(*this, ctx, start, end); }
144  GA_Offset start, GA_Offset end) const
145  { myTransformPageD(*this, ctx, start, end); }
147  GA_Offset offset) const
148  { myTransformF(*this, ctx, offset); }
150  GA_Offset offset) const
151  { myTransformD(*this, ctx, offset); }
152  /// @}
153 
154  /// Check to see whether the attribute is valid
155  bool isValid() const { return myType != GA_TYPE_VOID; }
156  /// Return the GA_TypeInfo for the attribute
157  GA_TypeInfo getType() const { return myType; }
158 
159  /// @{
160  /// Check whether length of vectors/normals should be preserved after
161  /// transforming.
162  bool keepLength() const { return myKeepLength; }
163  void setKeepLength(bool v) { myKeepLength = v; }
164  /// @}
165 
166  /// @{
167  /// Accessors to provide information in the callback handle functions
168  /// NOTE: Always check isDouble() before calling getV3!
169  GA_Attribute *getAttribute() const { return myAttribute; }
170  template<typename FLOAT_T>
172  {
174  UT_ASSERT_P(myIsDouble == (sizeof(FLOAT_T) == 8));
175  UT_ASSERT_P(!myIsDouble == (sizeof(FLOAT_T) == 4));
176  return (const GA_RWHandleT<UT_Vector3T<FLOAT_T> > &)myV3;
177  }
178  const GA_AIFMath *getMath() const { return myMath; }
179  const GA_AIFTuple *getTuple() const { return myTuple; }
180  /// @}
181 
182  /// @{
183  /// Check whether the inverse matrix or quaternion transform are
184  /// required
185  bool needInverse() const { return myNeedI; }
186  bool needQuaternion() const { return myNeedQ; }
187  /// @}
188 
189  /// Check if the attribute is double-precision, if can choose
190  /// between single and double-precision transformation.
191  bool isDouble() const { return myIsDouble; }
192 
193  private:
194  /// Set up the transform callback functions
195  void setupFunctions();
196 
197  GAtransformF myTransformF;
198  GAtransformD myTransformD;
199  GAtransformPageF myTransformPageF;
200  GAtransformPageD myTransformPageD;
201  GA_Attribute *myAttribute;
202  const GA_AIFMath *myMath;
203  const GA_AIFTuple *myTuple;
204  GA_RWHandleV3 myV3;
205  GA_TypeInfo myType;
206  bool myKeepLength;
207  bool myNeedI;
208  bool myNeedQ;
209  bool myIsDouble;
210  };
211 
212 public:
215 
216  /// Add all transformable attributes to the handle list. When @c
217  /// keep_length is set, normals and vectors will maintain their lengths
218  /// under scaling.
219  void addAttributes(bool keep_lengths=false);
220  /// Add a filtered selection of attributes to the handle list. The filter
221  /// should filter out non-transforming attributes. When @c keep_length is
222  /// set, normals and vectors will maintain their lengths under scaling.
223  void addAttributes(const GA_AttributeFilter &filter,
224  bool keep_lenghts=false);
225  /// Add a single transformable attributes to the handle list. When @c
226  /// keep_length is set, normals and vectors will maintain their lengths
227  /// under scaling.
228  void addAttribute(GA_Attribute *attrib,
229  bool keep_lengths=false);
230  /// Clear the list of transformable attributes.
231  void clearAttributes();
232 
233  /// Return the number of attributes which will be transformed
234  exint entries() const { return myHandles.entries(); }
235  /// Return the handle to the individual attribute
236  const Handle &getHandle(exint i) const { return myHandles(i); }
237  /// Return the bound detail
238  GA_Detail &getDetail() const { return myDetail; }
239 
240  /// @{
241  /// Perform the transformation on all attributes.
242  ///
243  /// @note The Transform reference is non-const. The methods are mostly
244  /// thread safe (provided threads access unique pages of data). However,
245  /// since the Transform object is non-const, the Transform should @b not be
246  /// shared across threads.
247  void transform(const GA_Range &range,
248  Transform<fpreal32> &m) const;
249  void transform(const GA_Range &range,
250  Transform<fpreal64> &m) const;
251  void transform(const GA_Range &range,
252  Transform<fpreal32> &m32,
253  Transform<fpreal64> &m64) const;
254  void transform(GA_Offset offset, Transform<fpreal32> &m) const;
255  void transform(GA_Offset offset, Transform<fpreal64> &m) const;
257  Transform<fpreal32> &m32,
258  Transform<fpreal64> &m64) const;
259  /// @}
260 
261  /// @{
262  /// Check whether any attributes require the inverse/quaternion transforms
263  bool needInverse() const { return myNeedI; }
264  bool needQuaternion() const { return myNeedQ; }
265  /// @}
266 
267  /// @{
268  /// Check whether any attributes are single- or double-precision
269  bool hasSingle() const { return myHasSingle; }
270  bool hasDouble() const { return myHasDouble; }
271  /// @}
272 
273 private:
274  /// Ensure the transform has its inverse/quaternion computed (if needed)
275  template <typename FLOAT_T>
276  void updateTransform(Transform<FLOAT_T> &xform) const
277  {
278  if (myNeedI)
279  xform.computeInverse();
280  if (myNeedQ)
281  xform.computeQuaternion();
282  }
283  GA_Detail &myDetail;
284  UT_Array<Handle> myHandles;
285  GA_AttributeOwner myOwner;
286  bool myNeedI;
287  bool myNeedQ;
288  bool myHasSingle;
289  bool myHasDouble;
290 };
291 
292 #endif
Definition of a geometry attribute.
Definition: GA_Attribute.h:198
Data has no numeric representation.
Definition: GA_Types.h:103
UT_ASSERT_COMPILETIME(BRAY_EVENT_MAXFLAGS<=32)
GLenum GLint * range
Definition: glcorearb.h:1925
void
Definition: png.h:1083
void transform(const Transform< fpreal32 > &ctx, GA_Offset start, GA_Offset end) const
Attribute Interface class to perform numeric operations on attributes.
Definition: GA_AIFMath.h:88
const GLdouble * v
Definition: glcorearb.h:837
Transform(const UT_Matrix4T< FLOAT_T2 > &m)
GLuint start
Definition: glcorearb.h:475
T determinant() const
Definition: UT_Matrix3.h:578
bool isValid() const
Check to see whether the attribute is valid.
void transform(const Transform< fpreal64 > &ctx, GA_Offset offset) const
GA_Detail & getDetail() const
Return the bound detail.
int64 exint
Definition: SYS_Types.h:125
Class to pass transforms to GA_AttributeTransformer.
#define GA_API
Definition: GA_API.h:14
A range of elements in an index-map.
Definition: GA_Range.h:42
void transform(const Transform< fpreal64 > &ctx, GA_Offset start, GA_Offset end) const
GA_Size GA_Offset
Definition: GA_Types.h:641
GLintptr offset
Definition: glcorearb.h:665
void set(const UT_Matrix4T< FLOAT_T2 > &m)
Set the matrix.
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
GLuint GLuint end
Definition: glcorearb.h:475
const UT_Matrix4T< FLOAT_T > & ixform() const
const UT_QuaternionT< FLOAT_T > & q() const
GA_TypeInfo getType() const
Return the GA_TypeInfo for the attribute.
GA_API const UT_StringHolder transform
const UT_Matrix4T< FLOAT_T > & xform() const
GA_TypeInfo
Definition: GA_Types.h:100
void transform(const Transform< fpreal32 > &ctx, GA_Offset offset) const
GA_AttributeOwner
Definition: GA_Types.h:34
const GA_RWHandleT< UT_Vector3T< FLOAT_T > > & getV3() const
Handle to a transformable attribute.
void computeInverse()
Compute the inverse (if required)
exint entries() const
Return the number of attributes which will be transformed.
Container class for all geometry.
Definition: GA_Detail.h:96
const GA_AIFTuple * getTuple() const
void computeQuaternion()
Compute the quaternion transform (if required)
const GA_AIFMath * getMath() const
Generic Attribute Interface class to access an attribute as a tuple.
Definition: GA_AIFTuple.h:32
Class to efficiently transform multiple attributes.
void * Handle
Definition: plugin.h:27
const Handle & getHandle(exint i) const
Return the handle to the individual attribute.
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glcorearb.h:1297