All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
importAttribute.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_IMPORT_ATTRIBUTE_H
26 #define USDDRACO_IMPORT_ATTRIBUTE_H
27 
28 #include "attributeDescriptor.h"
29 #include "attributeFactory.h"
30 
31 #include "pxr/pxr.h"
32 #include "pxr/usd/usdGeom/mesh.h"
33 #include "pxr/usd/usdGeom/primvarsAPI.h"
34 
35 #include <draco/attributes/point_attribute.h>
36 #include <draco/mesh/mesh.h>
37 
38 
39 PXR_NAMESPACE_OPEN_SCOPE
40 
41 
49 public:
50  virtual const UsdDracoAttributeDescriptor &GetDescriptor() const = 0;
51  virtual void SetToMesh(UsdGeomMesh *usdMesh) const = 0;
52  virtual void PopulateValues() = 0;
53  virtual int GetMappedIndex(draco::PointIndex pi) const = 0;
54  virtual void ResizeIndices(size_t size) = 0;
55  virtual void SetIndex(size_t at, int index) = 0;
56  virtual size_t GetNumValues() const = 0;
57  virtual size_t GetNumIndices() const = 0;
58  virtual bool HasPointAttribute() const = 0;
59 };
60 
61 
66 template <class T>
68 public:
70  const draco::Mesh &dracoMesh);
71  const UsdDracoAttributeDescriptor &GetDescriptor() const override;
72 
73  // Adds an attribute or primvar to USD mesh according to attribuite
74  // descriptor.
75  void SetToMesh(UsdGeomMesh *usdMesh) const override;
76 
77  // Populates member values array with data from Draco attribute.
78  void PopulateValues() override;
79  void PopulateValuesWithOrder(
80  const UsdDracoImportAttribute<int> &order, size_t numFaces,
81  const draco::Mesh &dracoMesh);
82 
83  // Returns mapped value from Draco attribute.
84  T GetMappedValue(draco::PointIndex pi) const;
85 
86  // Returns mapped index from Draco attribute.
87  int GetMappedIndex(draco::PointIndex pi) const override;
88 
89  const VtArray<T> &GetValues() const;
90  void ResizeIndices(size_t size) override;
91  void SetIndex(size_t at, int index) override;
92  size_t GetNumValues() const override;
93  size_t GetNumIndices() const override;
94  bool HasPointAttribute() const override;
95 
96 private:
97  const draco::PointAttribute *_GetFromMesh(
98  const draco::Mesh &dracoMesh);
99 
100  // Specialization for arithmetic types.
101  template <class T_ = T,
102  typename std::enable_if<std::is_arithmetic<T_>::value>::type* = nullptr>
103  void _GetAttributeValueSpecialized(draco::AttributeValueIndex avi) {
104  _pointAttribute->GetValue(avi, &_values[avi.value()]);
105  }
106 
107  // Specialization for GfHalf type.
108  template <class T_ = T,
109  typename std::enable_if<
110  std::is_same<T_, GfHalf>::value>::type* = nullptr>
111  void _GetAttributeValueSpecialized(draco::AttributeValueIndex avi) {
112  // USD halfs are stored as Draco 16-bit ints.
113  _pointAttribute->GetValue(avi, &_values[avi.value()]);
114  }
115 
116  // Specialization for vector types.
117  template <class T_ = T,
118  typename std::enable_if<GfIsGfVec<T_>::value>::type* = nullptr>
119  void _GetAttributeValueSpecialized(draco::AttributeValueIndex avi) {
120  _pointAttribute->GetValue(avi, _values[avi.value()].data());
121  }
122 
123  // Specialization for matrix types.
124  template <class T_ = T,
125  typename std::enable_if<GfIsGfMatrix<T_>::value>::type* = nullptr>
126  void _GetAttributeValueSpecialized(draco::AttributeValueIndex avi) {
127  _pointAttribute->GetValue(avi, _values[avi.value()].data());
128  }
129 
130  // Specialization for quaternion types.
131  template <class T_ = T,
132  typename std::enable_if<GfIsGfQuat<T_>::value>::type* = nullptr>
133  void _GetAttributeValueSpecialized(draco::AttributeValueIndex avi) {
134  // Split a length-four vector into quaternion components.
135  // TODO: Read directly from data buffer of the point attribute.
136  std::array<typename T::ScalarType, 4> quaternion;
137  _pointAttribute->GetValue(avi, quaternion.data());
138  T &value = _values[avi.value()];
139  value.SetReal(quaternion[0]);
140  value.SetImaginary(quaternion[1], quaternion[2], quaternion[3]);
141  }
142 
143 private:
144  const UsdDracoAttributeDescriptor _descriptor;
145  const draco::PointAttribute *_pointAttribute;
146  VtArray<T> _values;
147  VtArray<int> _indices;
148 };
149 
150 
151 template <class T>
153  UsdDracoAttributeDescriptor descriptor, const draco::Mesh &dracoMesh) :
154  _descriptor(descriptor), _pointAttribute(_GetFromMesh(dracoMesh)) {
155 }
156 
157 template <class T>
160  return _descriptor;
161 }
162 
163 template <class T>
164 const draco::PointAttribute *UsdDracoImportAttribute<T>::_GetFromMesh(
165  const draco::Mesh &dracoMesh) {
166  const bool hasMetadata =
167  _descriptor.GetAttributeType() == draco::GeometryAttribute::GENERIC;
168  const int attributeId = hasMetadata
169  ? dracoMesh.GetAttributeIdByMetadataEntry(
170  UsdDracoAttributeDescriptor::METADATA_NAME_KEY,
171  _descriptor.GetName().GetText())
172  : dracoMesh.GetNamedAttributeId(_descriptor.GetAttributeType());
173  return (attributeId == -1) ? nullptr : dracoMesh.attribute(attributeId);
174 }
175 
176 template <class T>
178  if (_pointAttribute == nullptr)
179  return;
180  if (_descriptor.GetIsPrimvar()) {
181  // Set data as a primvar.
182  const UsdGeomPrimvarsAPI api = UsdGeomPrimvarsAPI(usdMesh->GetPrim());
183  UsdGeomPrimvar primvar = api.CreatePrimvar(
184  _descriptor.GetName(),
185  UsdDracoAttributeFactory::GetSdfValueTypeName(_descriptor));
186  primvar.Set(_values, _descriptor.GetValuesTime());
187  primvar.SetIndices(_indices, _descriptor.GetIndicesTime());
188  if (_descriptor.GetInterpolation() == UsdGeomTokens->vertex) {
189  // TODO: While exporting to Draco, indices of primvars with vertex
190  // interpolation are converted to point to face corners. Such
191  // indices should be restored to point to vertices in order to
192  // reduce memory. Meeanwhile, the interpolation is changed to
193  // faceVarying.
194  primvar.SetInterpolation(UsdGeomTokens->faceVarying);
195  } else {
196  primvar.SetInterpolation(_descriptor.GetInterpolation());
197  }
198  } else {
199  // Set data as an attribute.
200  UsdAttribute attribute = usdMesh->GetPrim().CreateAttribute(
201  _descriptor.GetName(),
202  UsdDracoAttributeFactory::GetSdfValueTypeName(_descriptor));
203  attribute.Set(_values, _descriptor.GetValuesTime());
204  }
205 }
206 
207 template <class T>
209  if (_pointAttribute == nullptr)
210  return;
211  const size_t numValues = _pointAttribute->size();
212  _values.resize(numValues);
213  for (size_t i = 0; i < numValues; i++) {
214  const draco::AttributeValueIndex avi(i);
215  _GetAttributeValueSpecialized(avi);
216  }
217 }
218 
219 template <class T>
221  const UsdDracoImportAttribute<int> &order, size_t numFaces,
222  const draco::Mesh &dracoMesh) {
223  if (_pointAttribute == nullptr)
224  return;
225  const size_t numValues = _pointAttribute->size();
226  _values.resize(numValues);
227  std::vector<bool> populated(numValues, false);
228  for (size_t i = 0; i < numFaces; i++) {
229  const draco::Mesh::Face &face = dracoMesh.face(draco::FaceIndex(i));
230  for (size_t c = 0; c < 3; c++) {
231  const draco::PointIndex pi = face[c];
232  const int origIndex = order.GetMappedValue(pi);
233  if (!populated[origIndex]) {
234  _pointAttribute->GetMappedValue(pi, _values[origIndex].data());
235  populated[origIndex] = true;
236  }
237  }
238  }
239 }
240 
241 template <class T>
243  draco::PointIndex pi) const {
244  if (_pointAttribute == nullptr)
245  return T(0);
246  T value;
247  _pointAttribute->GetMappedValue(pi, &value);
248  return value;
249 }
250 
251 template <class T>
253  draco::PointIndex pi) const {
254  if (_pointAttribute == nullptr)
255  return -1;
256  return static_cast<int>(_pointAttribute->mapped_index(pi).value());
257 }
258 
259 template <class T>
261  return _values;
262 }
263 
264 template <class T>
266  if (_pointAttribute == nullptr)
267  return;
268  _indices.resize(size);
269 }
270 
271 template <class T>
272 inline void UsdDracoImportAttribute<T>::SetIndex(size_t at, int index) {
273  if (_pointAttribute == nullptr)
274  return;
275  _indices[at] = index;
276 }
277 
278 template <class T>
280  return _values.size();
281 }
282 
283 template <class T>
285  return _indices.size();
286 }
287 
288 template <class T>
290  return _pointAttribute != nullptr;
291 }
292 
293 
294 PXR_NAMESPACE_CLOSE_SCOPE
295 
296 #endif // USDDRACO_IMPORT_ATTRIBUTE_H
bool Set(const T &value, UsdTimeCode time=UsdTimeCode::Default()) const
Set the value of this attribute in the current UsdEditTarget to value at UsdTimeCode time...
Definition: attribute.h:466
USD_API UsdAttribute CreateAttribute(const TfToken &name, const SdfValueTypeName &typeName, bool custom, SdfVariability variability=SdfVariabilityVarying) const
Author scene description for the attribute named attrName at the current EditTarget if none already e...
USDGEOM_API UsdGeomPrimvar CreatePrimvar(const TfToken &attrName, const SdfValueTypeName &typeName, const TfToken &interpolation=TfToken(), int elementSize=-1) const
Author scene description to create an attribute on this prim that will be recognized as Primvar (i...
Scenegraph object for authoring and retrieving numeric, string, and array valued data, sampled over time.
Definition: attribute.h:176
UsdGeomPrimvarsAPI encodes geometric &quot;primitive variables&quot;, as UsdGeomPrimvar, which interpolate ac...
Definition: primvarsAPI.h:82
Helps to read and write mesh attributes while importing Draco meshes to USD.
bool Set(const T &value, UsdTimeCode time=UsdTimeCode::Default()) const
Set the attribute value of the Primvar at time.
Definition: primvar.h:444
USDGEOM_API TfStaticData< UsdGeomTokensType > UsdGeomTokens
A global variable with static, efficient TfTokens for use in all public USD API.
pointer data()
Return a non-const pointer to this array&#39;s data.
Definition: array.h:383
Base class for UsdDracoImportAttribute&lt;T&gt; classes.
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