All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
exportAttribute.h
1 //
2 // Copyright 2019 Google LLC
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 
25 #ifndef USDDRACO_EXPORT_ATTRIBUTE_H
26 #define USDDRACO_EXPORT_ATTRIBUTE_H
27 
28 #include "attributeDescriptor.h"
29 
30 #include "pxr/base/gf/matrix2f.h"
31 #include "pxr/pxr.h"
32 #include "pxr/usd/usdGeom/mesh.h"
33 #include "pxr/usd/usdGeom/primvarsAPI.h"
34 
35 #include <draco/attributes/geometry_attribute.h>
36 #include <draco/attributes/point_attribute.h>
37 #include <draco/mesh/mesh.h>
38 
39 
40 PXR_NAMESPACE_OPEN_SCOPE
41 
42 
50 public:
51  virtual const UsdDracoAttributeDescriptor &GetDescriptor() const = 0;
52  virtual void GetFromMesh(const UsdGeomMesh &usdMesh,
53  size_t numPositions) = 0;
54  virtual void SetToMesh(draco::Mesh *dracoMesh) = 0;
55  virtual void SetPointMapEntry(draco::PointIndex pointIndex,
56  size_t positionIndex, size_t cornerIndex) = 0;
57  virtual size_t GetNumValues() const = 0;
58  virtual size_t GetNumIndices() const = 0;
59  virtual bool UsesPositionIndex() const = 0;
60 };
61 
62 
67 template <class T>
69 public:
71  const UsdDracoAttributeDescriptor &GetDescriptor() const override;
72 
73  // Populates member arrays with data from USD mesh based on descriptor.
74  void GetFromMesh(const UsdGeomMesh &usdMesh, size_t numPositions) override;
75 
76  // Populates member values array with an ascending sequence (0, 1, 2, ...)
77  // of a given size.
78  void GetFromRange(size_t size);
79 
80  // Creates Draco mesh attribute, sets the values, and metadata.
81  void SetToMesh(draco::Mesh *dracoMesh) override;
82 
83  // Sets Draco mesh attribute point map entry.
84  void SetPointMapEntry(draco::PointIndex pointIndex, size_t entryIndex);
85 
86  // Sets Draco mesh attribute point map entry using either position index or
87  // corner index, depending on the USD attribute interpolation value.
88  void SetPointMapEntry(draco::PointIndex pointIndex,
89  size_t positionIndex, size_t cornerIndex) override;
90  void Clear();
91  size_t GetNumValues() const override;
92  size_t GetNumIndices() const override;
93  bool UsesPositionIndex() const override;
94  bool HasPointAttribute() const;
95 
96 private:
97  template <class S>
98  static void _MakeRange(VtArray<S> *array, size_t size);
99  void _SetAttributeValue(draco::AttributeValueIndex avi, size_t index);
100 
101  // Specialization for arithmetic types.
102  template <class T_ = T,
103  typename std::enable_if<std::is_arithmetic<T_>::value>::type* = nullptr>
104  void _SetAttributeValueSpecialized(
105  draco::AttributeValueIndex avi, const T &value) {
106  _pointAttribute->SetAttributeValue(avi, &value);
107  }
108 
109  // Specialization for GfHalf type.
110  template <class T_ = T,
111  typename std::enable_if<
112  std::is_same<T_, GfHalf>::value>::type* = nullptr>
113  void _SetAttributeValueSpecialized(
114  draco::AttributeValueIndex avi, const T &value) {
115  // USD halfs are stored as Draco 16-bit ints.
116  _pointAttribute->SetAttributeValue(avi, &value);
117  }
118 
119  // Specialization for vector types.
120  template <class T_ = T,
121  typename std::enable_if<GfIsGfVec<T_>::value>::type* = nullptr>
122  void _SetAttributeValueSpecialized(
123  draco::AttributeValueIndex avi, const T &value) {
124  _pointAttribute->SetAttributeValue(avi, value.data());
125  }
126 
127  // Specialization for matrix types.
128  template <class T_ = T,
129  typename std::enable_if<GfIsGfMatrix<T_>::value>::type* = nullptr>
130  void _SetAttributeValueSpecialized(
131  draco::AttributeValueIndex avi, const T &value) {
132  _pointAttribute->SetAttributeValue(avi, value.data());
133  }
134 
135  // Specialization for quaternion types.
136  template <class T_ = T,
137  typename std::enable_if<GfIsGfQuat<T_>::value>::type* = nullptr>
138  void _SetAttributeValueSpecialized(
139  draco::AttributeValueIndex avi, const T &value) {
140  // Combine quaternion components into a length-four vector.
141  // TODO: Write directly to data buffer of the point attribute.
142  std::array<typename T::ScalarType, 4> quaternion;
143  quaternion[0] = value.GetReal();
144  quaternion[1] = value.GetImaginary()[0];
145  quaternion[2] = value.GetImaginary()[1];
146  quaternion[3] = value.GetImaginary()[2];
147  _pointAttribute->SetAttributeValue(avi, quaternion.data());
148  }
149 
150 private:
151  UsdDracoAttributeDescriptor _descriptor;
152  draco::PointAttribute *_pointAttribute;
153  bool _usePositionIndex;
154  VtArray<T> _values;
155  VtArray<int> _indices;
156 };
157 
158 
159 template <class T>
161  const UsdDracoAttributeDescriptor &descriptor) :
162  _descriptor(descriptor),
163  _pointAttribute(nullptr),
164  _usePositionIndex(false) {}
165 
166 template <class T>
169  return _descriptor;
170 }
171 
172 template <class T>
174  const UsdGeomMesh &usdMesh, size_t numPositions) {
175  if (_descriptor.GetStatus() != UsdDracoAttributeDescriptor::VALID)
176  return;
177  if (_descriptor.GetIsPrimvar()) {
178  // Get data from a primvar.
179  const UsdGeomPrimvarsAPI api = UsdGeomPrimvarsAPI(usdMesh.GetPrim());
180  UsdGeomPrimvar primvar = api.GetPrimvar(_descriptor.GetName());
181  if (!primvar)
182  return;
183  primvar.GetAttr().Get(&_values, _descriptor.GetValuesTime());
184  primvar.GetIndices(&_indices, _descriptor.GetIndicesTime());
185 
186  // Primvars with constant interpolation are not exported and remain in
187  // the USD mesh. Primvars with vertex interpolation are exported as
188  // attributes associated with mesh vertices and may have implicit
189  // indices.
190  _usePositionIndex = primvar.GetInterpolation() == UsdGeomTokens->vertex;
191  if (_indices.empty() && _usePositionIndex &&
192  _values.size() == numPositions)
193  _MakeRange(&_indices, numPositions);
194  } else {
195  // Get data from an attribute.
196  UsdAttribute attribute =
197  usdMesh.GetPrim().GetAttribute(_descriptor.GetName());
198  if (attribute)
199  attribute.Get(&_values);
200  }
201 }
202 
203 template <class T>
204 void UsdDracoExportAttribute<T>::SetToMesh(draco::Mesh *dracoMesh) {
205  // Optional attributes like normals may not be present.
206  if (_values.empty())
207  return;
208 
209  // Create Draco attribtue.
210  draco::GeometryAttribute geometryAttr;
211  const size_t byteStride = _descriptor.GetNumComponents() *
212  draco::DataTypeLength(_descriptor.GetDataType());
213  geometryAttr.Init(_descriptor.GetAttributeType(),
214  nullptr /* buffer */,
215  _descriptor.GetNumComponents(),
216  _descriptor.GetDataType(),
217  false /* normalized */,
218  byteStride,
219  0 /* byteOffset */);
220  const int attributeId =
221  dracoMesh->AddAttribute(geometryAttr, false, _values.size());
222  _pointAttribute = dracoMesh->attribute(attributeId);
223 
224  // Populate Draco attribute values.
225  for (size_t i = 0; i < _values.size(); i++)
226  _SetAttributeValue(draco::AttributeValueIndex(i), i);
227 
228  // Set metadata for Draco attribute.
229  dracoMesh->AddAttributeMetadata(attributeId, _descriptor.ToMetadata());
230 }
231 
232 template <class T>
234  _MakeRange(&_values, size);
235 }
236 
237 template <class T>
238 template <class S>
240  VtArray<S> *array, size_t size) {
241  (*array).resize(size);
242  for (size_t i = 0; i < size; i++) {
243  (*array)[i] = static_cast<S>(i);
244  }
245 }
246 
247 template <class T>
249  draco::AttributeValueIndex avi, size_t index) {
250  _SetAttributeValueSpecialized(avi, _values[index]);
251 }
252 
253 template <class T>
255  draco::PointIndex pointIndex, size_t entryIndex) {
256  if (_pointAttribute == nullptr)
257  return;
258  _pointAttribute->SetPointMapEntry(
259  pointIndex, draco::AttributeValueIndex(entryIndex));
260 }
261 
262 template <class T>
264  draco::PointIndex pointIndex, size_t positionIndex,
265  size_t cornerIndex) {
266  if (_pointAttribute == nullptr)
267  return;
268  const size_t index = _usePositionIndex ? positionIndex : cornerIndex;
269  const size_t entryIndex = _indices[index];
270  SetPointMapEntry(pointIndex, entryIndex);
271 }
272 
273 template <class T>
275  _values.clear();
276  _indices.clear();
277  _usePositionIndex = false;
278  _pointAttribute = nullptr;
279 }
280 
281 template <class T>
283  return _values.size();
284 }
285 
286 template <class T>
288  return _indices.size();
289 }
290 
291 template <class T>
293  return _usePositionIndex;
294 }
295 
296 template <class T>
298  return _pointAttribute != nullptr;
299 }
300 
301 
302 PXR_NAMESPACE_CLOSE_SCOPE
303 
304 #endif // USDDRACO_EXPORT_ATTRIBUTE_H
Scenegraph object for authoring and retrieving numeric, string, and array valued data, sampled over time.
Definition: attribute.h:176
Helps to read and write mesh attributes while exporting USD meshes to Draco.
UsdGeomPrimvarsAPI encodes geometric &quot;primitive variables&quot;, as UsdGeomPrimvar, which interpolate ac...
Definition: primvarsAPI.h:82
UsdAttribute const & GetAttr() const
Explicit UsdAttribute extractor.
Definition: primvar.h:378
USDGEOM_API TfStaticData< UsdGeomTokensType > UsdGeomTokens
A global variable with static, efficient TfTokens for use in all public USD API.
Represents an arbitrary dimensional rectangular container class.
Definition: array.h:193
bool Get(T *value, UsdTimeCode time=UsdTimeCode::Default()) const
Perform value resolution to fetch the value of this attribute at the requested UsdTimeCode time...
Definition: attribute.h:435
Base class for UsdDracoExportAttribute&lt;T&gt; classes.
USDGEOM_API UsdGeomPrimvar GetPrimvar(const TfToken &name) const
Return the Primvar object named by name, which will be valid if a Primvar attribute definition alread...
USD_API UsdAttribute GetAttribute(const TfToken &attrName) const
Return a UsdAttribute with the name attrName.
Schema wrapper for UsdAttribute for authoring and introspecting attributes that are primvars...
Definition: primvar.h:260
Encodes a mesh surface whose definition and feature-set will converge with that of OpenSubdiv...
Definition: mesh.h:86
Stores description of mesh attributes, such as name, data type, shape, time sample, interpolation, etc.
UsdPrim GetPrim() const
Return this schema object&#39;s held prim.
Definition: schemaBase.h:119